getloadavg.c 26.1 KB
Newer Older
Roland McGrath's avatar
Roland McGrath committed
1
/* Get the system load averages.
2
   Copyright (C) 1985, 1986, 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995,
3 4
                 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007
                 Free Software Foundation, Inc.
Roland McGrath's avatar
Roland McGrath committed
5

6 7 8
   NOTE: The canonical source of this file is maintained with gnulib.
   Bugs can be reported to bug-gnulib@gnu.org.

Roland McGrath's avatar
Roland McGrath committed
9 10 11 12 13 14 15 16 17 18 19 20
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
Lute Kamstra's avatar
Lute Kamstra committed
21
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
Karl Heuer's avatar
Karl Heuer committed
22
   USA.  */
Roland McGrath's avatar
Roland McGrath committed
23 24 25

/* Compile-time symbols that this file uses:

26 27 28 29 30 31 32 33
   HAVE_PSTAT_GETDYNAMIC	Define this if your system has the
                                pstat_getdynamic function.  I think it
				is unique to HPUX9.  The best way to get the
				definition is through the AC_FUNC_GETLOADAVG
				macro that comes with autoconf 2.13 or newer.
				If that isn't an option, then just put
				AC_CHECK_FUNCS(pstat_getdynamic) in your
				configure.in file.
Roland McGrath's avatar
Roland McGrath committed
34 35 36 37 38 39 40 41
   FIXUP_KERNEL_SYMBOL_ADDR()	Adjust address in returned struct nlist.
   KERNEL_FILE			Pathname of the kernel to nlist.
   LDAV_CVT()			Scale the load average from the kernel.
				Returns a double.
   LDAV_SYMBOL			Name of kernel symbol giving load average.
   LOAD_AVE_TYPE		Type of the load average array in the kernel.
				Must be defined unless one of
				apollo, DGUX, NeXT, or UMAX is defined;
Paul D. Smith's avatar
Paul D. Smith committed
42
                                or we have libkstat;
Roland McGrath's avatar
Roland McGrath committed
43
				otherwise, no load average is available.
44 45
   HAVE_NLIST_H                 nlist.h is available.  NLIST_STRUCT defaults
                                to this.
Roland McGrath's avatar
Roland McGrath committed
46 47 48
   NLIST_STRUCT			Include nlist.h, not a.out.h, and
				the nlist n_name element is a pointer,
				not an array.
49
   HAVE_STRUCT_NLIST_N_UN_N_NAME `n_un.n_name' is member of `struct nlist'.
Roland McGrath's avatar
Roland McGrath committed
50
   LINUX_LDAV_FILE		[__linux__]: File containing load averages.
51 52
   HAVE_LOCALE_H                locale.h is available.
   HAVE_SETLOCALE               The `setlocale' function is available.
Roland McGrath's avatar
Roland McGrath committed
53 54 55 56 57 58

   Specific system predefines this file uses, aside from setting
   default values if not emacs:

   apollo
   BSD				Real BSD, not just BSD-like.
59
   convex
Roland McGrath's avatar
Roland McGrath committed
60 61 62
   DGUX
   eunice			UNIX emulator under VMS.
   hpux
Paul D. Smith's avatar
Paul D. Smith committed
63
   __MSDOS__			No-op for MSDOS.
Roland McGrath's avatar
Roland McGrath committed
64 65 66 67 68 69 70 71
   NeXT
   sgi
   sequent			Sequent Dynix 3.x.x (BSD)
   _SEQUENT_			Sequent DYNIX/ptx 1.x.x (SYSV)
   sony_news                    NEWS-OS (works at least for 4.1C)
   UMAX
   UMAX4_3
   VMS
Paul D. Smith's avatar
Paul D. Smith committed
72
   WINDOWS32			No-op for Windows95/NT.
Roland McGrath's avatar
Roland McGrath committed
73
   __linux__			Linux: assumes /proc filesystem mounted.
Roland McGrath's avatar
Roland McGrath committed
74
   				Support from Michael K. Johnson.
Roland McGrath's avatar
Roland McGrath committed
75
   __NetBSD__			NetBSD: assumes /kern filesystem mounted.
Roland McGrath's avatar
Roland McGrath committed
76 77 78 79 80 81 82

   In addition, to avoid nesting many #ifdefs, we internally set
   LDAV_DONE to indicate that the load average has been computed.

   We also #define LDAV_PRIVILEGED if a program will require
   special installation to be able to call getloadavg.  */

Roland McGrath's avatar
Roland McGrath committed
83 84
/* This should always be first.  */
#ifdef HAVE_CONFIG_H
85
# include <config.h>
Roland McGrath's avatar
Roland McGrath committed
86 87
#endif

Roland McGrath's avatar
Roland McGrath committed
88 89 90 91 92
#include <sys/types.h>

/* Both the Emacs and non-Emacs sections want this.  Some
   configuration files' definitions for the LOAD_AVE_CVT macro (like
   sparc.h's) use macros like FSCALE, defined here.  */
93
#if defined (unix) || defined (__unix)
94
# include <sys/param.h>
Roland McGrath's avatar
Roland McGrath committed
95 96 97
#endif


Roland McGrath's avatar
Roland McGrath committed
98
/* Exclude all the code except the test program at the end
99 100 101 102 103 104 105 106 107 108
   if the system has its own `getloadavg' function.

   The declaration of `errno' is needed by the test program
   as well as the function itself, so it comes first.  */

#include <errno.h>

#ifndef errno
extern int errno;
#endif
Roland McGrath's avatar
Roland McGrath committed
109

110 111 112 113 114 115
#ifdef HAVE_LOCALE_H
# include <locale.h>
#endif
#ifndef HAVE_SETLOCALE
# define setlocale(Category, Locale) /* empty */
#endif
Roland McGrath's avatar
Roland McGrath committed
116

117
#ifndef HAVE_GETLOADAVG
Roland McGrath's avatar
Roland McGrath committed
118

Roland McGrath's avatar
Roland McGrath committed
119 120 121 122 123 124 125 126 127 128
/* The existing Emacs configuration files define a macro called
   LOAD_AVE_CVT, which accepts a value of type LOAD_AVE_TYPE, and
   returns the load average multiplied by 100.  What we actually want
   is a macro called LDAV_CVT, which returns the load average as an
   unmultiplied double.

   For backwards compatibility, we'll define LDAV_CVT in terms of
   LOAD_AVE_CVT, but future machine config files should just define
   LDAV_CVT directly.  */

129 130 131
# if !defined(LDAV_CVT) && defined(LOAD_AVE_CVT)
#  define LDAV_CVT(n) (LOAD_AVE_CVT (n) / 100.0)
# endif
Roland McGrath's avatar
Roland McGrath committed
132

133
# if !defined (BSD) && defined (ultrix)
Roland McGrath's avatar
Roland McGrath committed
134
/* Ultrix behaves like BSD on Vaxen.  */
135 136
#  define BSD
# endif
Roland McGrath's avatar
Roland McGrath committed
137

138
# ifdef NeXT
Roland McGrath's avatar
Roland McGrath committed
139 140 141
/* NeXT in the 2.{0,1,2} releases defines BSD in <sys/param.h>, which
   conflicts with the definition understood in this file, that this
   really is BSD. */
142
#  undef BSD
Roland McGrath's avatar
Roland McGrath committed
143 144 145

/* NeXT defines FSCALE in <sys/param.h>.  However, we take FSCALE being
   defined to mean that the nlist method should be used, which is not true.  */
146 147
#  undef FSCALE
# endif
Roland McGrath's avatar
Roland McGrath committed
148

149 150 151 152 153 154
/* Same issues as for NeXT apply to the HURD-based GNU system.  */
# ifdef __GNU__
#  undef BSD
#  undef FSCALE
# endif /* __GNU__ */

Roland McGrath's avatar
Roland McGrath committed
155 156 157 158 159 160
/* Set values that are different from the defaults, which are
   set a little farther down with #ifndef.  */


/* Some shorthands.  */

161 162 163
# if defined (HPUX) && !defined (hpux)
#  define hpux
# endif
Roland McGrath's avatar
Roland McGrath committed
164

165 166 167
# if defined (__hpux) && !defined (hpux)
#  define hpux
# endif
168

169 170 171
# if defined (__sun) && !defined (sun)
#  define sun
# endif
172

173 174 175
# if defined(hp300) && !defined(hpux)
#  define MORE_BSD
# endif
Roland McGrath's avatar
Roland McGrath committed
176

177 178 179
# if defined(ultrix) && defined(mips)
#  define decstation
# endif
Roland McGrath's avatar
Roland McGrath committed
180

181 182 183
# if defined (__SVR4) && !defined (SVR4)
#  define SVR4
# endif
Roland McGrath's avatar
Roland McGrath committed
184

185 186 187
# if (defined(sun) && defined(SVR4)) || defined (SOLARIS2)
#  define SUNOS_5
# endif
Roland McGrath's avatar
Roland McGrath committed
188

189 190
# if defined (__osf__) && (defined (__alpha) || defined (__alpha__))
#  define OSF_ALPHA
191 192 193
#  include <sys/mbuf.h>
#  include <sys/socket.h>
#  include <net/route.h>
194 195 196 197 198 199 200
#  include <sys/table.h>
# endif

# if defined (__osf__) && (defined (mips) || defined (__mips__))
#  define OSF_MIPS
#  include <sys/table.h>
# endif
Roland McGrath's avatar
Roland McGrath committed
201 202 203 204

/* UTek's /bin/cc on the 4300 has no architecture specific cpp define by
   default, but _MACH_IND_SYS_TYPES is defined in <sys/types.h>.  Combine
   that with a couple of other things and we'll have a unique match.  */
205 206 207
# if !defined (tek4300) && defined (unix) && defined (m68k) && defined (mc68000) && defined (mc68020) && defined (_MACH_IND_SYS_TYPES)
#  define tek4300			/* Define by emacs, but not by other users.  */
# endif
Roland McGrath's avatar
Roland McGrath committed
208 209


Jim Blandy's avatar
Jim Blandy committed
210
/* VAX C can't handle multi-line #ifs, or lines longer than 256 chars.  */
211
# ifndef LOAD_AVE_TYPE
Roland McGrath's avatar
Roland McGrath committed
212

213 214 215
#  ifdef MORE_BSD
#   define LOAD_AVE_TYPE long
#  endif
Jim Blandy's avatar
Jim Blandy committed
216

217 218 219
#  ifdef sun
#   define LOAD_AVE_TYPE long
#  endif
Jim Blandy's avatar
Jim Blandy committed
220

221 222 223
#  ifdef decstation
#   define LOAD_AVE_TYPE long
#  endif
Jim Blandy's avatar
Jim Blandy committed
224

225 226 227
#  ifdef _SEQUENT_
#   define LOAD_AVE_TYPE long
#  endif
Jim Blandy's avatar
Jim Blandy committed
228

229 230 231
#  ifdef sgi
#   define LOAD_AVE_TYPE long
#  endif
Jim Blandy's avatar
Jim Blandy committed
232

233 234 235
#  ifdef SVR4
#   define LOAD_AVE_TYPE long
#  endif
Jim Blandy's avatar
Jim Blandy committed
236

237 238 239
#  ifdef sony_news
#   define LOAD_AVE_TYPE long
#  endif
Jim Blandy's avatar
Jim Blandy committed
240

241 242 243
#  ifdef sequent
#   define LOAD_AVE_TYPE long
#  endif
Jim Blandy's avatar
Jim Blandy committed
244

245 246 247
#  ifdef OSF_ALPHA
#   define LOAD_AVE_TYPE long
#  endif
Jim Blandy's avatar
Jim Blandy committed
248

249 250 251
#  if defined (ardent) && defined (titan)
#   define LOAD_AVE_TYPE long
#  endif
Jim Blandy's avatar
Jim Blandy committed
252

253 254 255
#  ifdef tek4300
#   define LOAD_AVE_TYPE long
#  endif
Roland McGrath's avatar
Roland McGrath committed
256

257 258 259
#  if defined(alliant) && defined(i860) /* Alliant FX/2800 */
#   define LOAD_AVE_TYPE long
#  endif
260

261 262 263
#  ifdef _AIX
#   define LOAD_AVE_TYPE long
#  endif
264

265 266 267 268 269 270
#  ifdef convex
#   define LOAD_AVE_TYPE double
#   ifndef LDAV_CVT
#    define LDAV_CVT(n) (n)
#   endif
#  endif
271

272
# endif /* No LOAD_AVE_TYPE.  */
Roland McGrath's avatar
Roland McGrath committed
273

274
# ifdef OSF_ALPHA
Roland McGrath's avatar
Roland McGrath committed
275 276
/* <sys/param.h> defines an incorrect value for FSCALE on Alpha OSF/1,
   according to ghazi@noc.rutgers.edu.  */
277 278 279
#  undef FSCALE
#  define FSCALE 1024.0
# endif
Roland McGrath's avatar
Roland McGrath committed
280

281
# if defined(alliant) && defined(i860) /* Alliant FX/2800 */
282 283
/* <sys/param.h> defines an incorrect value for FSCALE on an
   Alliant FX/2800 Concentrix 2.2, according to ghazi@noc.rutgers.edu.  */
284 285 286
#  undef FSCALE
#  define FSCALE 100.0
# endif
287

Roland McGrath's avatar
Roland McGrath committed
288

289
# ifndef	FSCALE
Roland McGrath's avatar
Roland McGrath committed
290 291 292

/* SunOS and some others define FSCALE in sys/param.h.  */

293 294 295
#  ifdef MORE_BSD
#   define FSCALE 2048.0
#  endif
Roland McGrath's avatar
Roland McGrath committed
296

297 298 299
#  if defined(MIPS) || defined(SVR4) || defined(decstation)
#   define FSCALE 256
#  endif
Roland McGrath's avatar
Roland McGrath committed
300

301
#  if defined (sgi) || defined (sequent)
Roland McGrath's avatar
Roland McGrath committed
302 303
/* Sometimes both MIPS and sgi are defined, so FSCALE was just defined
   above under #ifdef MIPS.  But we want the sgi value.  */
304
#   undef FSCALE
305
#   define FSCALE 1000.0
306
#  endif
Roland McGrath's avatar
Roland McGrath committed
307

308 309 310
#  if defined (ardent) && defined (titan)
#   define FSCALE 65536.0
#  endif
Roland McGrath's avatar
Roland McGrath committed
311

312 313 314
#  ifdef tek4300
#   define FSCALE 100.0
#  endif
315

316 317 318
#  ifdef _AIX
#   define FSCALE 65536.0
#  endif
319

320
# endif	/* Not FSCALE.  */
Roland McGrath's avatar
Roland McGrath committed
321

322
# if !defined (LDAV_CVT) && defined (FSCALE)
323
#  define LDAV_CVT(n) (((double) (n)) / FSCALE)
324
# endif
Roland McGrath's avatar
Roland McGrath committed
325

326 327 328 329 330
# ifndef NLIST_STRUCT
#  if HAVE_NLIST_H
#   define NLIST_STRUCT
#  endif
# endif
Roland McGrath's avatar
Roland McGrath committed
331

332 333 334
# if defined(sgi) || (defined(mips) && !defined(BSD))
#  define FIXUP_KERNEL_SYMBOL_ADDR(nl) ((nl)[0].n_value &= ~(1 << 31))
# endif
Roland McGrath's avatar
Roland McGrath committed
335 336


337 338 339
# if !defined (KERNEL_FILE) && defined (sequent)
#  define KERNEL_FILE "/dynix"
# endif
Roland McGrath's avatar
Roland McGrath committed
340

341 342 343
# if !defined (KERNEL_FILE) && defined (hpux)
#  define KERNEL_FILE "/hp-ux"
# endif
Roland McGrath's avatar
Roland McGrath committed
344

345 346 347
# if !defined(KERNEL_FILE) && (defined(_SEQUENT_) || defined(MIPS) || defined(SVR4) || defined(ISC) || defined (sgi) || (defined (ardent) && defined (titan)))
#  define KERNEL_FILE "/unix"
# endif
Roland McGrath's avatar
Roland McGrath committed
348 349


350 351 352
# if !defined (LDAV_SYMBOL) && defined (alliant)
#  define LDAV_SYMBOL "_Loadavg"
# endif
Roland McGrath's avatar
Roland McGrath committed
353

354 355 356
# 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
Roland McGrath's avatar
Roland McGrath committed
357

358 359 360
# ifdef HAVE_UNISTD_H
#  include <unistd.h>
# endif
Roland McGrath's avatar
Roland McGrath committed
361

362
# include <stdio.h>
Roland McGrath's avatar
Roland McGrath committed
363 364 365

/* LOAD_AVE_TYPE should only get defined if we're going to use the
   nlist method.  */
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
# 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 /* NLIST_STRUCT */
#     include <nlist.h>
#    endif /* NLIST_STRUCT */

#    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 /* KERNEL_FILE */

#    ifndef LDAV_SYMBOL
#     define LDAV_SYMBOL "_avenrun"
#    endif /* LDAV_SYMBOL */
#   endif /* __linux__ */

#  else /* VMS */

#   ifndef eunice
#    include <iodef.h>
#    include <descrip.h>
#   else /* eunice */
#    include <vms/iodef.h>
#   endif /* eunice */
#  endif /* VMS */

#  ifndef LDAV_CVT
#   define LDAV_CVT(n) ((double) (n))
#  endif /* !LDAV_CVT */

# endif /* LOAD_AVE_TYPE */

415 416 417 418
# if defined(__GNU__) && !defined (NeXT)
/* Note that NeXT Openstep defines __GNU__ even though it should not.  */
/* GNU system acts much like NeXT, for load average purposes,
   but not exactly.  */
Miles Bader's avatar
Miles Bader committed
419 420 421 422
#  define NeXT
#  define host_self mach_host_self
# endif

423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
# ifdef NeXT
#  ifdef HAVE_MACH_MACH_H
#   include <mach/mach.h>
#  else
#   include <mach.h>
#  endif
# endif /* NeXT */

# ifdef sgi
#  include <sys/sysmp.h>
# endif /* sgi */

# 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 /* Not UMAX_43.  */
#   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 /* Not UMAX_43.  */
# endif /* UMAX */

# 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
Roland McGrath's avatar
Roland McGrath committed
467 468 469

/* Avoid static vars inside a function since in HPUX they dump as pure.  */

470
# ifdef NeXT
Roland McGrath's avatar
Roland McGrath committed
471 472
static processor_set_t default_set;
static int getloadavg_initialized;
473
# endif /* NeXT */
Roland McGrath's avatar
Roland McGrath committed
474

475
# ifdef UMAX
Roland McGrath's avatar
Roland McGrath committed
476 477
static unsigned int cpus = 0;
static unsigned int samples;
478
# endif /* UMAX */
Roland McGrath's avatar
Roland McGrath committed
479

480
# ifdef DGUX
Roland McGrath's avatar
Roland McGrath committed
481
static struct dg_sys_info_load_info load_info;	/* what-a-mouthful! */
482
# endif /* DGUX */
Roland McGrath's avatar
Roland McGrath committed
483

Paul D. Smith's avatar
Paul D. Smith committed
484
#if !defined(HAVE_LIBKSTAT) && defined(LOAD_AVE_TYPE)
Roland McGrath's avatar
Roland McGrath committed
485 486 487 488 489 490 491
/* File descriptor open to /dev/kmem or VMS load ave driver.  */
static int channel;
/* Nonzero iff channel is valid.  */
static int getloadavg_initialized;
/* Offset in kmem to seek to read load average, or 0 means invalid.  */
static long offset;

492
#  if !defined(VMS) && !defined(sgi) && !defined(__linux__)
Roland McGrath's avatar
Roland McGrath committed
493
static struct nlist nl[2];
494
#  endif /* Not VMS or sgi */
Roland McGrath's avatar
Roland McGrath committed
495

496
#  ifdef SUNOS_5
Roland McGrath's avatar
Roland McGrath committed
497
static kvm_t *kd;
498
#  endif /* SUNOS_5 */
Roland McGrath's avatar
Roland McGrath committed
499

500
#endif /* LOAD_AVE_TYPE && !HAVE_LIBKSTAT */
Roland McGrath's avatar
Roland McGrath committed
501 502 503

/* Put the 1 minute, 5 minute and 15 minute load averages
   into the first NELEM elements of LOADAVG.
David J. MacKenzie's avatar
David J. MacKenzie committed
504
   Return the number written (never more than 3, but may be less than NELEM),
Roland McGrath's avatar
Roland McGrath committed
505 506 507 508 509 510 511 512 513
   or -1 if an error occurred.  */

int
getloadavg (loadavg, nelem)
     double loadavg[];
     int nelem;
{
  int elem = 0;			/* Return value.  */

514 515
# ifdef NO_GET_LOAD_AVG
#  define LDAV_DONE
Roland McGrath's avatar
Roland McGrath committed
516 517 518 519
  /* Set errno to zero to indicate that there was no particular error;
     this function just can't work at all on this system.  */
  errno = 0;
  elem = -1;
520
# endif
Roland McGrath's avatar
Roland McGrath committed
521

Paul D. Smith's avatar
Paul D. Smith committed
522
# if !defined (LDAV_DONE) && defined (HAVE_LIBKSTAT)
523
/* Use libkstat because we don't have to be root.  */
524
#  define LDAV_DONE
525 526 527 528 529
  kstat_ctl_t *kc;
  kstat_t *ksp;
  kstat_named_t *kn;

  kc = kstat_open ();
530 531
  if (kc == 0)
    return -1;
532
  ksp = kstat_lookup (kc, "unix", 0, "system_misc");
533 534 535 536
  if (ksp == 0 )
    return -1;
  if (kstat_read (kc, ksp, 0) == -1)
    return -1;
537

538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566

  kn = kstat_data_lookup (ksp, "avenrun_1min");
  if (kn == 0)
    {
      /* Return -1 if no load average information is available.  */
      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);
Paul D. Smith's avatar
Paul D. Smith committed
567
# endif /* HAVE_LIBKSTAT */
568

569 570 571 572
# if !defined (LDAV_DONE) && defined (hpux) && defined (HAVE_PSTAT_GETDYNAMIC)
/* Use pstat_getdynamic() because we don't have to be root.  */
#  define LDAV_DONE
#  undef LOAD_AVE_TYPE
Roland McGrath's avatar
Roland McGrath committed
573

574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592
  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 /* hpux && HAVE_PSTAT_GETDYNAMIC */

# if !defined (LDAV_DONE) && defined (__linux__)
#  define LDAV_DONE
#  undef LOAD_AVE_TYPE

#  ifndef LINUX_LDAV_FILE
#   define LINUX_LDAV_FILE "/proc/loadavg"
#  endif
Roland McGrath's avatar
Roland McGrath committed
593 594 595 596 597 598 599 600 601 602 603 604 605

  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;

606 607
  /* The following sscanf must use the C locale.  */
  setlocale (LC_NUMERIC, "C");
Roland McGrath's avatar
Roland McGrath committed
608 609
  count = sscanf (ldavgbuf, "%lf %lf %lf",
		  &load_ave[0], &load_ave[1], &load_ave[2]);
610
  setlocale (LC_NUMERIC, "");
Roland McGrath's avatar
Roland McGrath committed
611 612 613 614 615 616 617 618
  if (count < 1)
    return -1;

  for (elem = 0; elem < nelem && elem < count; elem++)
    loadavg[elem] = load_ave[elem];

  return elem;

619
# endif /* __linux__ */
Roland McGrath's avatar
Roland McGrath committed
620

621 622 623
# if !defined (LDAV_DONE) && defined (__NetBSD__)
#  define LDAV_DONE
#  undef LOAD_AVE_TYPE
Roland McGrath's avatar
Roland McGrath committed
624

625 626 627
#  ifndef NETBSD_LDAV_FILE
#   define NETBSD_LDAV_FILE "/kern/loadavg"
#  endif
Roland McGrath's avatar
Roland McGrath committed
628 629 630 631 632

  unsigned long int load_ave[3], scale;
  int count;
  FILE *fp;

Roland McGrath's avatar
Roland McGrath committed
633
  fp = fopen (NETBSD_LDAV_FILE, "r");
Roland McGrath's avatar
Roland McGrath committed
634 635 636 637 638 639 640 641 642 643 644 645 646 647
  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;

648
# endif /* __NetBSD__ */
Roland McGrath's avatar
Roland McGrath committed
649

650 651
# if !defined (LDAV_DONE) && defined (NeXT)
#  define LDAV_DONE
Roland McGrath's avatar
Roland McGrath committed
652 653 654 655 656 657
  /* The NeXT code was adapted from iscreen 3.2.  */

  host_t host;
  struct processor_set_basic_info info;
  unsigned info_count;

David J. MacKenzie's avatar
David J. MacKenzie committed
658 659
  /* We only know how to get the 1-minute average for this system,
     so even if the caller asks for more than 1, we only return 1.  */
Roland McGrath's avatar
Roland McGrath committed
660 661 662 663 664 665 666 667 668 669 670

  if (!getloadavg_initialized)
    {
      if (processor_set_default (host_self (), &default_set) == KERN_SUCCESS)
	getloadavg_initialized = 1;
    }

  if (getloadavg_initialized)
    {
      info_count = PROCESSOR_SET_BASIC_INFO_COUNT;
      if (processor_set_info (default_set, PROCESSOR_SET_BASIC_INFO, &host,
671
			      (processor_set_info_t) &info, &info_count)
Roland McGrath's avatar
Roland McGrath committed
672 673 674 675 676 677 678 679 680 681 682
	  != KERN_SUCCESS)
	getloadavg_initialized = 0;
      else
	{
	  if (nelem > 0)
	    loadavg[elem++] = (double) info.load_average / LOAD_SCALE;
	}
    }

  if (!getloadavg_initialized)
    return -1;
683
# endif /* NeXT */
Roland McGrath's avatar
Roland McGrath committed
684

685 686
# if !defined (LDAV_DONE) && defined (UMAX)
#  define LDAV_DONE
Roland McGrath's avatar
Roland McGrath committed
687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752
/* UMAX 4.2, which runs on the Encore Multimax multiprocessor, does not
   have a /dev/kmem.  Information about the workings of the running kernel
   can be gathered with inq_stats system calls.
   We only know how to get the 1-minute average for this system.  */

  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;
753
# endif /* UMAX */
Roland McGrath's avatar
Roland McGrath committed
754

755 756
# if !defined (LDAV_DONE) && defined (DGUX)
#  define LDAV_DONE
Roland McGrath's avatar
Roland McGrath committed
757 758 759 760 761 762 763 764 765 766 767 768 769
  /* This call can return -1 for an error, but with good args
     it's not supposed to fail.  The first argument is for no
     apparent reason of type `long int *'.  */
  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;
770
# endif /* DGUX */
Roland McGrath's avatar
Roland McGrath committed
771

772 773
# if !defined (LDAV_DONE) && defined (apollo)
#  define LDAV_DONE
Roland McGrath's avatar
Roland McGrath committed
774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794
/* Apollo code from lisch@mentorg.com (Ray Lischner).

   This system call is not documented.  The load average is obtained as
   three long integers, for the load average over the past minute,
   five minutes, and fifteen minutes.  Each value is a scaled integer,
   with 16 bits of integer part and 16 bits of fraction part.

   I'm not sure which operating system first supported this system call,
   but I know that SR10.2 supports it.  */

  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;
795
# endif /* apollo */
Roland McGrath's avatar
Roland McGrath committed
796

797 798
# if !defined (LDAV_DONE) && defined (OSF_MIPS)
#  define LDAV_DONE
Roland McGrath's avatar
Roland McGrath committed
799 800 801

  struct tbl_loadavg load_ave;
  table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave));
Roland McGrath's avatar
Roland McGrath committed
802 803 804 805
  loadavg[elem++]
    = (load_ave.tl_lscale == 0
       ? load_ave.tl_avenrun.d[0]
       : (load_ave.tl_avenrun.l[0] / (double) load_ave.tl_lscale));
806
# endif	/* OSF_MIPS */
Roland McGrath's avatar
Roland McGrath committed
807

Paul D. Smith's avatar
Paul D. Smith committed
808
# if !defined (LDAV_DONE) && (defined (__MSDOS__) || defined (WINDOWS32))
809
#  define LDAV_DONE
810 811

  /* A faithful emulation is going to have to be saved for a rainy day.  */
812
  for ( ; elem < nelem; elem++)
813 814 815
    {
      loadavg[elem] = 0.0;
    }
Paul D. Smith's avatar
Paul D. Smith committed
816
# endif  /* __MSDOS__ || WINDOWS32 */
817

818 819
# if !defined (LDAV_DONE) && defined (OSF_ALPHA)
#  define LDAV_DONE
820 821 822 823 824 825 826 827

  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));
828
# endif /* OSF_ALPHA */
829

830
# if !defined (LDAV_DONE) && defined (VMS)
Roland McGrath's avatar
Roland McGrath committed
831 832 833 834
  /* VMS specific code -- read from the Load Ave driver.  */

  LOAD_AVE_TYPE load_ave[3];
  static int getloadavg_initialized = 0;
835
#  ifdef eunice
Roland McGrath's avatar
Roland McGrath committed
836 837 838 839 840
  struct
  {
    int dsc$w_length;
    char *dsc$a_pointer;
  } descriptor;
841
#  endif
Roland McGrath's avatar
Roland McGrath committed
842 843 844 845 846

  /* Ensure that there is a channel open to the load ave device.  */
  if (!getloadavg_initialized)
    {
      /* Attempt to open the channel.  */
847
#  ifdef eunice
Roland McGrath's avatar
Roland McGrath committed
848 849
      descriptor.dsc$w_length = 18;
      descriptor.dsc$a_pointer = "$$VMS_LOAD_AVERAGE";
850
#  else
Roland McGrath's avatar
Roland McGrath committed
851
      $DESCRIPTOR (descriptor, "LAV0:");
852
#  endif
Roland McGrath's avatar
Roland McGrath committed
853 854 855 856 857 858 859 860 861 862 863 864 865 866 867
      if (sys$assign (&descriptor, &channel, 0, 0) & 1)
	getloadavg_initialized = 1;
    }

  /* Read the load average vector.  */
  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;
868
# endif /* VMS */
Roland McGrath's avatar
Roland McGrath committed
869

870
# if !defined (LDAV_DONE) && defined(LOAD_AVE_TYPE) && !defined(VMS)
Roland McGrath's avatar
Roland McGrath committed
871 872 873

  /* UNIX-specific code -- read the average from /dev/kmem.  */

874
#  define LDAV_PRIVILEGED		/* This code requires special installation.  */
Roland McGrath's avatar
Roland McGrath committed
875 876 877 878 879 880

  LOAD_AVE_TYPE load_ave[3];

  /* Get the address of LDAV_SYMBOL.  */
  if (offset == 0)
    {
881 882
#  ifndef sgi
#   ifndef NLIST_STRUCT
Roland McGrath's avatar
Roland McGrath committed
883 884
      strcpy (nl[0].n_name, LDAV_SYMBOL);
      strcpy (nl[1].n_name, "");
885
#   else /* NLIST_STRUCT */
886
#    ifdef HAVE_STRUCT_NLIST_N_UN_N_NAME
Roland McGrath's avatar
Roland McGrath committed
887 888
      nl[0].n_un.n_name = LDAV_SYMBOL;
      nl[1].n_un.n_name = 0;
889
#    else /* not HAVE_STRUCT_NLIST_N_UN_N_NAME */
Roland McGrath's avatar
Roland McGrath committed
890 891
      nl[0].n_name = LDAV_SYMBOL;
      nl[1].n_name = 0;
892
#    endif /* not HAVE_STRUCT_NLIST_N_UN_N_NAME */
893
#   endif /* NLIST_STRUCT */
Roland McGrath's avatar
Roland McGrath committed
894

895
#   ifndef SUNOS_5
896
      if (
897
#    if !(defined (_AIX) && !defined (ps2))
898
	  nlist (KERNEL_FILE, nl)
899
#    else  /* _AIX */
900
	  knlist (nl, 1, sizeof (nl[0]))
901
#    endif
902 903 904
	  >= 0)
	  /* Omit "&& nl[0].n_type != 0 " -- it breaks on Sun386i.  */
	  {
905
#    ifdef FIXUP_KERNEL_SYMBOL_ADDR
906
	    FIXUP_KERNEL_SYMBOL_ADDR (nl);
907
#    endif
908 909
	    offset = nl[0].n_value;
	  }
910 911 912 913 914 915 916 917 918
#   endif /* !SUNOS_5 */
#  else  /* sgi */
      int ldav_off;

      ldav_off = sysmp (MP_KERNADDR, MPKA_AVENRUN);
      if (ldav_off != -1)
	offset = (long) ldav_off & 0x7fffffff;
#  endif /* sgi */
    }
Roland McGrath's avatar
Roland McGrath committed
919 920 921 922

  /* Make sure we have /dev/kmem open.  */
  if (!getloadavg_initialized)
    {
923
#  ifndef SUNOS_5
Roland McGrath's avatar
Roland McGrath committed
924 925
      channel = open ("/dev/kmem", 0);
      if (channel >= 0)
926 927 928
	{
	  /* Set the channel to close on exec, so it does not
	     litter any child's descriptor table.  */
929
#   ifdef F_SETFD
930 931 932
#    ifndef FD_CLOEXEC
#     define FD_CLOEXEC 1
#    endif
933
	  (void) fcntl (channel, F_SETFD, FD_CLOEXEC);
934
#   endif
935 936
	  getloadavg_initialized = 1;
	}
937
#  else /* SUNOS_5 */
David J. MacKenzie's avatar
David J. MacKenzie committed
938 939
      /* We pass 0 for the kernel, corefile, and swapfile names
	 to use the currently running kernel.  */
Roland McGrath's avatar
Roland McGrath committed
940
      kd = kvm_open (0, 0, 0, O_RDONLY, 0);
941
      if (kd != 0)
Roland McGrath's avatar
Roland McGrath committed
942
	{
David J. MacKenzie's avatar
David J. MacKenzie committed
943
	  /* nlist the currently running kernel.  */
Roland McGrath's avatar
Roland McGrath committed
944
	  kvm_nlist (kd, nl);
David J. MacKenzie's avatar
David J. MacKenzie committed
945
	  offset = nl[0].n_value;
Roland McGrath's avatar
Roland McGrath committed
946 947
	  getloadavg_initialized = 1;
	}
948
#  endif /* SUNOS_5 */
Roland McGrath's avatar
Roland McGrath committed
949 950 951 952 953 954
    }

  /* If we can, get the load average values.  */
  if (offset && getloadavg_initialized)
    {
      /* Try to read the load.  */
955
#  ifndef SUNOS_5
Roland McGrath's avatar
Roland McGrath committed
956 957 958 959 960 961 962
      if (lseek (channel, offset, 0) == -1L
	  || read (channel, (char *) load_ave, sizeof (load_ave))
	  != sizeof (load_ave))
	{
	  close (channel);
	  getloadavg_initialized = 0;
	}
963
#  else  /* SUNOS_5 */
Roland McGrath's avatar
Roland McGrath committed
964 965 966 967 968 969
      if (kvm_read (kd, offset, (char *) load_ave, sizeof (load_ave))
	  != sizeof (load_ave))
        {
          kvm_close (kd);
          getloadavg_initialized = 0;
	}
970
#  endif /* SUNOS_5 */
Roland McGrath's avatar
Roland McGrath committed
971 972 973 974
    }

  if (offset == 0 || !getloadavg_initialized)
    return -1;
975
# endif /* LOAD_AVE_TYPE and not VMS */
Roland McGrath's avatar
Roland McGrath committed
976

977
# if !defined (LDAV_DONE) && defined (LOAD_AVE_TYPE) /* Including VMS.  */
Roland McGrath's avatar
Roland McGrath committed
978 979 980 981 982 983 984
  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]);

985 986
#  define LDAV_DONE
# endif /* !LDAV_DONE && LOAD_AVE_TYPE */
Roland McGrath's avatar
Roland McGrath committed
987

988
# ifdef LDAV_DONE
Roland McGrath's avatar
Roland McGrath committed
989
  return elem;
990
# else
Roland McGrath's avatar
Roland McGrath committed
991 992 993 994
  /* Set errno to zero to indicate that there was no particular error;
     this function just can't work at all on this system.  */
  errno = 0;
  return -1;
995
# endif
Roland McGrath's avatar
Roland McGrath committed
996
}
Roland McGrath's avatar
Roland McGrath committed
997 998

#endif /* ! HAVE_GETLOADAVG */
Roland McGrath's avatar
Roland McGrath committed
999 1000

#ifdef TEST
1001
void
Roland McGrath's avatar
Roland McGrath committed
1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
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;		/* Don't be misled if it doesn't set errno.  */
      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');
Roland McGrath's avatar
Roland McGrath committed
1031 1032 1033

      if (naptime == 0)
	break;
Roland McGrath's avatar
Roland McGrath committed
1034 1035
      sleep (naptime);
    }
Roland McGrath's avatar
Roland McGrath committed
1036 1037

  exit (0);
Roland McGrath's avatar
Roland McGrath committed
1038 1039
}
#endif /* TEST */
Miles Bader's avatar
Miles Bader committed
1040 1041 1042

/* arch-tag: 2b37a242-6289-41f4-8cd5-0e73fd615db1
   (do not change this comment) */