1 /* Get the system load averages.
2 Copyright (C) 1985, 86, 87, 88, 89, 91, 92, 93, 1994
3 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19 /* Compile-time symbols that this file uses:
21 FIXUP_KERNEL_SYMBOL_ADDR() Adjust address in returned struct nlist.
22 KERNEL_FILE Pathname of the kernel to nlist.
23 LDAV_CVT() Scale the load average from the kernel.
25 LDAV_SYMBOL Name of kernel symbol giving load average.
26 LOAD_AVE_TYPE Type of the load average array in the kernel.
27 Must be defined unless one of
28 apollo, DGUX, NeXT, or UMAX is defined;
29 otherwise, no load average is available.
30 NLIST_STRUCT Include nlist.h, not a.out.h, and
31 the nlist n_name element is a pointer,
33 NLIST_NAME_UNION struct nlist has an n_un member, not n_name.
34 LINUX_LDAV_FILE [__linux__]: File containing load averages.
36 Specific system predefines this file uses, aside from setting
37 default values if not emacs:
40 BSD Real BSD, not just BSD-like.
42 eunice UNIX emulator under VMS.
46 sequent Sequent Dynix 3.x.x (BSD)
47 _SEQUENT_ Sequent DYNIX/ptx 1.x.x (SYSV)
48 sony_news NEWS-OS (works at least for 4.1C)
52 __linux__ Linux: assumes /proc filesystem mounted.
53 Support from Michael K. Johnson.
54 __NetBSD__ NetBSD: assumes /kern filesystem mounted.
56 In addition, to avoid nesting many #ifdefs, we internally set
57 LDAV_DONE to indicate that the load average has been computed.
59 We also #define LDAV_PRIVILEGED if a program will require
60 special installation to be able to call getloadavg. */
62 #include <sys/types.h>
64 /* Both the Emacs and non-Emacs sections want this. Some
65 configuration files' definitions for the LOAD_AVE_CVT macro (like
66 sparc.h's) use macros like FSCALE, defined here. */
68 #include <sys/param.h>
73 #if defined (emacs) || defined (CONFIG_BROKETS)
74 /* We use <config.h> instead of "config.h" so that a compilation
75 using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
76 (which it would do because it found this file in $srcdir). */
83 /* Exclude all the code except the test program at the end
84 if the system has its own `getloadavg' function.
86 The declaration of `errno' is needed by the test program
87 as well as the function itself, so it comes first. */
95 #ifndef HAVE_GETLOADAVG
98 /* The existing Emacs configuration files define a macro called
99 LOAD_AVE_CVT, which accepts a value of type LOAD_AVE_TYPE, and
100 returns the load average multiplied by 100. What we actually want
101 is a macro called LDAV_CVT, which returns the load average as an
104 For backwards compatibility, we'll define LDAV_CVT in terms of
105 LOAD_AVE_CVT, but future machine config files should just define
106 LDAV_CVT directly. */
108 #if !defined(LDAV_CVT) && defined(LOAD_AVE_CVT)
109 #define LDAV_CVT(n) (LOAD_AVE_CVT (n) / 100.0)
112 #if !defined (BSD) && defined (ultrix)
113 /* Ultrix behaves like BSD on Vaxen. */
118 /* NeXT in the 2.{0,1,2} releases defines BSD in <sys/param.h>, which
119 conflicts with the definition understood in this file, that this
123 /* NeXT defines FSCALE in <sys/param.h>. However, we take FSCALE being
124 defined to mean that the nlist method should be used, which is not true. */
128 /* Set values that are different from the defaults, which are
129 set a little farther down with #ifndef. */
132 /* Some shorthands. */
134 #if defined (HPUX) && !defined (hpux)
138 #if defined(hp300) && !defined(hpux)
142 #if defined(ultrix) && defined(mips)
146 #if defined(sun) && defined(SVR4)
150 #if defined (__osf__) && (defined (__alpha) || defined (__alpha__))
154 #if defined (__osf__) && (defined (mips) || defined (__mips__))
156 #include <sys/table.h>
159 /* UTek's /bin/cc on the 4300 has no architecture specific cpp define by
160 default, but _MACH_IND_SYS_TYPES is defined in <sys/types.h>. Combine
161 that with a couple of other things and we'll have a unique match. */
162 #if !defined (tek4300) && defined (unix) && defined (m68k) && defined (mc68000) && defined (mc68020) && defined (_MACH_IND_SYS_TYPES)
163 #define tek4300 /* Define by emacs, but not by other users. */
167 /* VAX C can't handle multi-line #ifs, or lines longer than 256 chars. */
168 #ifndef LOAD_AVE_TYPE
171 #define LOAD_AVE_TYPE long
175 #define LOAD_AVE_TYPE long
179 #define LOAD_AVE_TYPE long
183 #define LOAD_AVE_TYPE long
187 #define LOAD_AVE_TYPE long
191 #define LOAD_AVE_TYPE long
195 #define LOAD_AVE_TYPE long
199 #define LOAD_AVE_TYPE long
203 #define LOAD_AVE_TYPE long
206 #if defined (ardent) && defined (titan)
207 #define LOAD_AVE_TYPE long
211 #define LOAD_AVE_TYPE long
214 #endif /* No LOAD_AVE_TYPE. */
217 /* <sys/param.h> defines an incorrect value for FSCALE on Alpha OSF/1,
218 according to ghazi@noc.rutgers.edu. */
220 #define FSCALE 1024.0
226 /* SunOS and some others define FSCALE in sys/param.h. */
229 #define FSCALE 2048.0
232 #if defined(MIPS) || defined(SVR4) || defined(decstation)
236 #if defined (sgi) || defined (sequent)
237 /* Sometimes both MIPS and sgi are defined, so FSCALE was just defined
238 above under #ifdef MIPS. But we want the sgi value. */
240 #define FSCALE 1000.0
243 #if defined (ardent) && defined (titan)
244 #define FSCALE 65536.0
251 #endif /* Not FSCALE. */
253 #if !defined (LDAV_CVT) && defined (FSCALE)
254 #define LDAV_CVT(n) (((double) (n)) / FSCALE)
257 /* VAX C can't handle multi-line #ifs, or lines longer that 256 characters. */
276 #if defined (_SEQUENT_) || defined (sequent)
296 #if defined (ardent) && defined (titan)
308 #endif /* defined (NLIST_STRUCT) */
311 #if defined(sgi) || (defined(mips) && !defined(BSD))
312 #define FIXUP_KERNEL_SYMBOL_ADDR(nl) ((nl)[0].n_value &= ~(1 << 31))
316 #if !defined (KERNEL_FILE) && defined (sequent)
317 #define KERNEL_FILE "/dynix"
320 #if !defined (KERNEL_FILE) && defined (hpux)
321 #define KERNEL_FILE "/hp-ux"
324 #if !defined(KERNEL_FILE) && (defined(_SEQUENT_) || defined(MIPS) || defined(SVR4) || defined(ISC) || defined (sgi) || defined(SVR4) || (defined (ardent) && defined (titan)))
325 #define KERNEL_FILE "/unix"
329 #if !defined (LDAV_SYMBOL) && defined (alliant)
330 #define LDAV_SYMBOL "_Loadavg"
333 #if !defined(LDAV_SYMBOL) && ((defined(hpux) && !defined(hp9000s300)) || defined(_SEQUENT_) || defined(SVR4) || defined(ISC) || defined(sgi) || (defined (ardent) && defined (titan)))
334 #define LDAV_SYMBOL "avenrun"
343 /* LOAD_AVE_TYPE should only get defined if we're going to use the
345 #if !defined(LOAD_AVE_TYPE) && (defined(BSD) || defined(LDAV_CVT) || defined(KERNEL_FILE) || defined(LDAV_SYMBOL))
346 #define LOAD_AVE_TYPE double
354 #else /* NLIST_STRUCT */
356 #endif /* NLIST_STRUCT */
364 #define KERNEL_FILE "/vmunix"
365 #endif /* KERNEL_FILE */
368 #define LDAV_SYMBOL "_avenrun"
369 #endif /* LDAV_SYMBOL */
377 #include <vms/iodef.h>
382 #define LDAV_CVT(n) ((double) (n))
383 #endif /* !LDAV_CVT */
385 #endif /* LOAD_AVE_TYPE */
388 #ifdef HAVE_MACH_MACH_H
389 #include <mach/mach.h>
396 #include <sys/sysmp.h>
402 #include <sys/time.h>
403 #include <sys/wait.h>
404 #include <sys/syscall.h>
407 #include <machine/cpu.h>
408 #include <inq_stats/statistics.h>
409 #include <inq_stats/sysstats.h>
410 #include <inq_stats/cpustats.h>
411 #include <inq_stats/procstats.h>
412 #else /* Not UMAX_43. */
413 #include <sys/sysdefs.h>
414 #include <sys/statistics.h>
415 #include <sys/sysstats.h>
416 #include <sys/cpudefs.h>
417 #include <sys/cpustats.h>
418 #include <sys/procstats.h>
419 #endif /* Not UMAX_43. */
423 #include <sys/dg_sys_info.h>
426 #if defined(HAVE_FCNTL_H) || defined(_POSIX_VERSION)
429 #include <sys/file.h>
432 /* Avoid static vars inside a function since in HPUX they dump as pure. */
435 static processor_set_t default_set
;
436 static int getloadavg_initialized
;
440 static unsigned int cpus
= 0;
441 static unsigned int samples
;
445 static struct dg_sys_info_load_info load_info
; /* what-a-mouthful! */
449 /* File descriptor open to /dev/kmem or VMS load ave driver. */
451 /* Nonzero iff channel is valid. */
452 static int getloadavg_initialized
;
453 /* Offset in kmem to seek to read load average, or 0 means invalid. */
456 #if !defined(VMS) && !defined(sgi)
457 static struct nlist nl
[2];
458 #endif /* Not VMS or sgi */
464 #endif /* LOAD_AVE_TYPE */
466 /* Put the 1 minute, 5 minute and 15 minute load averages
467 into the first NELEM elements of LOADAVG.
468 Return the number written (never more than 3, but may be less than NELEM),
469 or -1 if an error occurred. */
472 getloadavg (loadavg
, nelem
)
476 int elem
= 0; /* Return value. */
478 #ifdef NO_GET_LOAD_AVG
480 /* Set errno to zero to indicate that there was no particular error;
481 this function just can't work at all on this system. */
486 #if !defined (LDAV_DONE) && defined (__linux__)
490 #ifndef LINUX_LDAV_FILE
491 #define LINUX_LDAV_FILE "/proc/loadavg"
498 fd
= open (LINUX_LDAV_FILE
, O_RDONLY
);
501 count
= read (fd
, ldavgbuf
, 40);
506 count
= sscanf (ldavgbuf
, "%lf %lf %lf",
507 &load_ave
[0], &load_ave
[1], &load_ave
[2]);
511 for (elem
= 0; elem
< nelem
&& elem
< count
; elem
++)
512 loadavg
[elem
] = load_ave
[elem
];
516 #endif /* __linux__ */
518 #if !defined (LDAV_DONE) && defined (__NetBSD__)
522 #ifndef NETBSD_LDAV_FILE
523 #define NETBSD_LDAV_FILE "/kern/loadavg"
526 unsigned long int load_ave
[3], scale
;
530 fp
= fopen (NETBSD_LDAV_FILE
, "r");
533 count
= fscanf (fp
, "%lu %lu %lu %lu\n",
534 &load_ave
[0], &load_ave
[1], &load_ave
[2],
540 for (elem
= 0; elem
< nelem
; elem
++)
541 loadavg
[elem
] = (double) load_ave
[elem
] / (double) scale
;
545 #endif /* __NetBSD__ */
547 #if !defined (LDAV_DONE) && defined (NeXT)
549 /* The NeXT code was adapted from iscreen 3.2. */
552 struct processor_set_basic_info info
;
555 /* We only know how to get the 1-minute average for this system,
556 so even if the caller asks for more than 1, we only return 1. */
558 if (!getloadavg_initialized
)
560 if (processor_set_default (host_self (), &default_set
) == KERN_SUCCESS
)
561 getloadavg_initialized
= 1;
564 if (getloadavg_initialized
)
566 info_count
= PROCESSOR_SET_BASIC_INFO_COUNT
;
567 if (processor_set_info (default_set
, PROCESSOR_SET_BASIC_INFO
, &host
,
568 (processor_set_info_t
) &info
, &info_count
)
570 getloadavg_initialized
= 0;
574 loadavg
[elem
++] = (double) info
.load_average
/ LOAD_SCALE
;
578 if (!getloadavg_initialized
)
582 #if !defined (LDAV_DONE) && defined (UMAX)
584 /* UMAX 4.2, which runs on the Encore Multimax multiprocessor, does not
585 have a /dev/kmem. Information about the workings of the running kernel
586 can be gathered with inq_stats system calls.
587 We only know how to get the 1-minute average for this system. */
589 struct proc_summary proc_sum_data
;
590 struct stat_descr proc_info
;
592 register unsigned int i
, j
;
596 register unsigned int c
, i
;
597 struct cpu_config conf
;
598 struct stat_descr desc
;
601 desc
.sd_subsys
= SUBSYS_CPU
;
602 desc
.sd_type
= CPUTYPE_CONFIG
;
603 desc
.sd_addr
= (char *) &conf
;
604 desc
.sd_size
= sizeof conf
;
606 if (inq_stats (1, &desc
))
610 for (i
= 0; i
< conf
.config_maxclass
; ++i
)
612 struct class_stats stats
;
613 bzero ((char *) &stats
, sizeof stats
);
615 desc
.sd_type
= CPUTYPE_CLASS
;
617 desc
.sd_addr
= (char *) &stats
;
618 desc
.sd_size
= sizeof stats
;
620 if (inq_stats (1, &desc
))
623 c
+= stats
.class_numcpus
;
626 samples
= cpus
< 2 ? 3 : (2 * cpus
/ 3);
629 proc_info
.sd_next
= 0;
630 proc_info
.sd_subsys
= SUBSYS_PROC
;
631 proc_info
.sd_type
= PROCTYPE_SUMMARY
;
632 proc_info
.sd_addr
= (char *) &proc_sum_data
;
633 proc_info
.sd_size
= sizeof (struct proc_summary
);
634 proc_info
.sd_sizeused
= 0;
636 if (inq_stats (1, &proc_info
) != 0)
639 load
= proc_sum_data
.ps_nrunnable
;
641 for (i
= samples
- 1; i
> 0; --i
)
643 load
+= proc_sum_data
.ps_nrun
[j
];
644 if (j
++ == PS_NRUNSIZE
)
649 loadavg
[elem
++] = load
/ samples
/ cpus
;
652 #if !defined (LDAV_DONE) && defined (DGUX)
654 /* This call can return -1 for an error, but with good args
655 it's not supposed to fail. The first argument is for no
656 apparent reason of type `long int *'. */
657 dg_sys_info ((long int *) &load_info
,
658 DG_SYS_INFO_LOAD_INFO_TYPE
,
659 DG_SYS_INFO_LOAD_VERSION_0
);
662 loadavg
[elem
++] = load_info
.one_minute
;
664 loadavg
[elem
++] = load_info
.five_minute
;
666 loadavg
[elem
++] = load_info
.fifteen_minute
;
669 #if !defined (LDAV_DONE) && defined (apollo)
671 /* Apollo code from lisch@mentorg.com (Ray Lischner).
673 This system call is not documented. The load average is obtained as
674 three long integers, for the load average over the past minute,
675 five minutes, and fifteen minutes. Each value is a scaled integer,
676 with 16 bits of integer part and 16 bits of fraction part.
678 I'm not sure which operating system first supported this system call,
679 but I know that SR10.2 supports it. */
681 extern void proc1_$
get_loadav ();
682 unsigned long load_ave
[3];
684 proc1_$
get_loadav (load_ave
);
687 loadavg
[elem
++] = load_ave
[0] / 65536.0;
689 loadavg
[elem
++] = load_ave
[1] / 65536.0;
691 loadavg
[elem
++] = load_ave
[2] / 65536.0;
694 #if !defined (LDAV_DONE) && defined (OSF_MIPS)
697 struct tbl_loadavg load_ave
;
698 table (TBL_LOADAVG
, 0, &load_ave
, 1, sizeof (load_ave
));
700 = (load_ave
.tl_lscale
== 0
701 ? load_ave
.tl_avenrun
.d
[0]
702 : (load_ave
.tl_avenrun
.l
[0] / (double) load_ave
.tl_lscale
));
703 #endif /* OSF_MIPS */
705 #if !defined (LDAV_DONE) && defined (VMS)
706 /* VMS specific code -- read from the Load Ave driver. */
708 LOAD_AVE_TYPE load_ave
[3];
709 static int getloadavg_initialized
= 0;
718 /* Ensure that there is a channel open to the load ave device. */
719 if (!getloadavg_initialized
)
721 /* Attempt to open the channel. */
723 descriptor
.dsc$w_length
= 18;
724 descriptor
.dsc$a_pointer
= "$$VMS_LOAD_AVERAGE";
726 $
DESCRIPTOR (descriptor
, "LAV0:");
728 if (sys$
assign (&descriptor
, &channel
, 0, 0) & 1)
729 getloadavg_initialized
= 1;
732 /* Read the load average vector. */
733 if (getloadavg_initialized
734 && !(sys$
qiow (0, channel
, IO$_READVBLK
, 0, 0, 0,
735 load_ave
, 12, 0, 0, 0, 0) & 1))
737 sys$
dassgn (channel
);
738 getloadavg_initialized
= 0;
741 if (!getloadavg_initialized
)
745 #if !defined (LDAV_DONE) && defined(LOAD_AVE_TYPE) && !defined(VMS)
747 /* UNIX-specific code -- read the average from /dev/kmem. */
749 #define LDAV_PRIVILEGED /* This code requires special installation. */
751 LOAD_AVE_TYPE load_ave
[3];
753 /* Get the address of LDAV_SYMBOL. */
758 strcpy (nl
[0].n_name
, LDAV_SYMBOL
);
759 strcpy (nl
[1].n_name
, "");
760 #else /* NLIST_STRUCT */
761 #ifdef NLIST_NAME_UNION
762 nl
[0].n_un
.n_name
= LDAV_SYMBOL
;
763 nl
[1].n_un
.n_name
= 0;
764 #else /* not NLIST_NAME_UNION */
765 nl
[0].n_name
= LDAV_SYMBOL
;
767 #endif /* not NLIST_NAME_UNION */
768 #endif /* NLIST_STRUCT */
771 if (nlist (KERNEL_FILE
, nl
) >= 0)
772 /* Omit "&& nl[0].n_type != 0 " -- it breaks on Sun386i. */
774 #ifdef FIXUP_KERNEL_SYMBOL_ADDR
775 FIXUP_KERNEL_SYMBOL_ADDR (nl
);
777 offset
= nl
[0].n_value
;
779 #endif /* !SUNOS_5 */
783 ldav_off
= sysmp (MP_KERNADDR
, MPKA_AVENRUN
);
785 offset
= (long) ldav_off
& 0x7fffffff;
789 /* Make sure we have /dev/kmem open. */
790 if (!getloadavg_initialized
)
793 channel
= open ("/dev/kmem", 0);
795 getloadavg_initialized
= 1;
797 /* We pass 0 for the kernel, corefile, and swapfile names
798 to use the currently running kernel. */
799 kd
= kvm_open (0, 0, 0, O_RDONLY
, 0);
802 /* nlist the currently running kernel. */
804 offset
= nl
[0].n_value
;
805 getloadavg_initialized
= 1;
810 /* If we can, get the load average values. */
811 if (offset
&& getloadavg_initialized
)
813 /* Try to read the load. */
815 if (lseek (channel
, offset
, 0) == -1L
816 || read (channel
, (char *) load_ave
, sizeof (load_ave
))
817 != sizeof (load_ave
))
820 getloadavg_initialized
= 0;
823 if (kvm_read (kd
, offset
, (char *) load_ave
, sizeof (load_ave
))
824 != sizeof (load_ave
))
827 getloadavg_initialized
= 0;
832 if (offset
== 0 || !getloadavg_initialized
)
834 #endif /* LOAD_AVE_TYPE and not VMS */
836 #if !defined (LDAV_DONE) && defined (LOAD_AVE_TYPE) /* Including VMS. */
838 loadavg
[elem
++] = LDAV_CVT (load_ave
[0]);
840 loadavg
[elem
++] = LDAV_CVT (load_ave
[1]);
842 loadavg
[elem
++] = LDAV_CVT (load_ave
[2]);
845 #endif /* !LDAV_DONE && LOAD_AVE_TYPE */
850 /* Set errno to zero to indicate that there was no particular error;
851 this function just can't work at all on this system. */
857 #endif /* ! HAVE_GETLOADAVG */
868 naptime
= atoi (argv
[1]);
875 errno
= 0; /* Don't be misled if it doesn't set errno. */
876 loads
= getloadavg (avg
, 3);
879 perror ("Error getting load average");
883 printf ("1-minute: %f ", avg
[0]);
885 printf ("5-minute: %f ", avg
[1]);
887 printf ("15-minute: %f ", avg
[2]);