summaryrefslogtreecommitdiffstats
path: root/lib/getloadavg.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/getloadavg.c')
-rw-r--r--lib/getloadavg.c149
1 files changed, 67 insertions, 82 deletions
diff --git a/lib/getloadavg.c b/lib/getloadavg.c
index c6b6fee..2a50131 100644
--- a/lib/getloadavg.c
+++ b/lib/getloadavg.c
@@ -1,7 +1,7 @@
1/* Get the system load averages. 1/* Get the system load averages.
2 2
3 Copyright (C) 1985, 1986, 1987, 1988, 1989, 1991, 1992, 1993, 1994, 3 Copyright (C) 1985, 1986, 1987, 1988, 1989, 1991, 1992, 1993, 1994,
4 1995, 1997, 1999, 2000, 2003, 2004 Free Software Foundation, Inc. 4 1995, 1997, 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
5 5
6 NOTE: The canonical source of this file is maintained with gnulib. 6 NOTE: The canonical source of this file is maintained with gnulib.
7 Bugs can be reported to bug-gnulib@gnu.org. 7 Bugs can be reported to bug-gnulib@gnu.org.
@@ -18,7 +18,7 @@
18 18
19 You should have received a copy of the GNU General Public License 19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software 20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22 USA. */ 22 USA. */
23 23
24/* Compile-time symbols that this file uses: 24/* Compile-time symbols that this file uses:
@@ -32,7 +32,7 @@
32 AC_CHECK_FUNCS(pstat_getdynamic) in your 32 AC_CHECK_FUNCS(pstat_getdynamic) in your
33 configure.in file. 33 configure.in file.
34 FIXUP_KERNEL_SYMBOL_ADDR() Adjust address in returned struct nlist. 34 FIXUP_KERNEL_SYMBOL_ADDR() Adjust address in returned struct nlist.
35 KERNEL_FILE Pathname of the kernel to nlist. 35 KERNEL_FILE Name of the kernel file to nlist.
36 LDAV_CVT() Scale the load average from the kernel. 36 LDAV_CVT() Scale the load average from the kernel.
37 Returns a double. 37 Returns a double.
38 LDAV_SYMBOL Name of kernel symbol giving load average. 38 LDAV_SYMBOL Name of kernel symbol giving load average.
@@ -47,9 +47,8 @@
47 the nlist n_name element is a pointer, 47 the nlist n_name element is a pointer,
48 not an array. 48 not an array.
49 HAVE_STRUCT_NLIST_N_UN_N_NAME `n_un.n_name' is member of `struct nlist'. 49 HAVE_STRUCT_NLIST_N_UN_N_NAME `n_un.n_name' is member of `struct nlist'.
50 LINUX_LDAV_FILE [__linux__]: File containing load averages. 50 LINUX_LDAV_FILE [__linux__, __CYGWIN__]: File containing
51 HAVE_LOCALE_H locale.h is available. 51 load averages.
52 HAVE_SETLOCALE The `setlocale' function is available.
53 52
54 Specific system predefines this file uses, aside from setting 53 Specific system predefines this file uses, aside from setting
55 default values if not emacs: 54 default values if not emacs:
@@ -70,9 +69,10 @@
70 UMAX4_3 69 UMAX4_3
71 VMS 70 VMS
72 WINDOWS32 No-op for Windows95/NT. 71 WINDOWS32 No-op for Windows95/NT.
73 __linux__ Linux: assumes /proc filesystem mounted. 72 __linux__ Linux: assumes /proc file system mounted.
74 Support from Michael K. Johnson. 73 Support from Michael K. Johnson.
75 __NetBSD__ NetBSD: assumes /kern filesystem mounted. 74 __CYGWIN__ Cygwin emulates linux /proc/loadavg.
75 __NetBSD__ NetBSD: assumes /kern file system mounted.
76 76
77 In addition, to avoid nesting many #ifdefs, we internally set 77 In addition, to avoid nesting many #ifdefs, we internally set
78 LDAV_DONE to indicate that the load average has been computed. 78 LDAV_DONE to indicate that the load average has been computed.
@@ -85,38 +85,29 @@
85# include <config.h> 85# include <config.h>
86#endif 86#endif
87 87
88#include <sys/types.h> 88#include <errno.h>
89 89#include <stdbool.h>
90/* Both the Emacs and non-Emacs sections want this. Some 90#include <stdio.h>
91 configuration files' definitions for the LOAD_AVE_CVT macro (like 91#include <stdlib.h>
92 sparc.h's) use macros like FSCALE, defined here. */
93#if defined (unix) || defined (__unix)
94# include <sys/param.h>
95#endif
96
97 92
98/* Exclude all the code except the test program at the end 93/* Exclude all the code except the test program at the end
99 if the system has its own `getloadavg' function. 94 if the system has its own `getloadavg' function. */
100 95
101 The declaration of `errno' is needed by the test program 96#ifndef HAVE_GETLOADAVG
102 as well as the function itself, so it comes first. */
103
104#include <errno.h>
105
106#ifndef errno
107extern int errno;
108#endif
109 97
110#ifdef HAVE_LOCALE_H 98# include <sys/types.h>
111# include <locale.h>
112#endif
113#ifndef HAVE_SETLOCALE
114# define setlocale(Category, Locale) /* empty */
115#endif
116 99
117#include "cloexec.h" 100/* Both the Emacs and non-Emacs sections want this. Some
101 configuration files' definitions for the LOAD_AVE_CVT macro (like
102 sparc.h's) use macros like FSCALE, defined here. */
103# if defined (unix) || defined (__unix)
104# include <sys/param.h>
105# endif
118 106
119#ifndef HAVE_GETLOADAVG 107# include "c-strtod.h"
108# include "cloexec.h"
109# include "intprops.h"
110# include "xalloc.h"
120 111
121/* The existing Emacs configuration files define a macro called 112/* The existing Emacs configuration files define a macro called
122 LOAD_AVE_CVT, which accepts a value of type LOAD_AVE_TYPE, and 113 LOAD_AVE_CVT, which accepts a value of type LOAD_AVE_TYPE, and
@@ -357,11 +348,7 @@ extern int errno;
357# define LDAV_SYMBOL "avenrun" 348# define LDAV_SYMBOL "avenrun"
358# endif 349# endif
359 350
360# ifdef HAVE_UNISTD_H 351# include <unistd.h>
361# include <unistd.h>
362# endif
363
364# include <stdio.h>
365 352
366/* LOAD_AVE_TYPE should only get defined if we're going to use the 353/* LOAD_AVE_TYPE should only get defined if we're going to use the
367 nlist method. */ 354 nlist method. */
@@ -435,7 +422,6 @@ extern int errno;
435# endif /* sgi */ 422# endif /* sgi */
436 423
437# ifdef UMAX 424# ifdef UMAX
438# include <stdio.h>
439# include <signal.h> 425# include <signal.h>
440# include <sys/time.h> 426# include <sys/time.h>
441# include <sys/wait.h> 427# include <sys/wait.h>
@@ -461,17 +447,13 @@ extern int errno;
461# include <sys/dg_sys_info.h> 447# include <sys/dg_sys_info.h>
462# endif 448# endif
463 449
464# if defined (HAVE_FCNTL_H) || defined (_POSIX_VERSION) 450# include "fcntl--.h"
465# include <fcntl.h>
466# else
467# include <sys/file.h>
468# endif
469 451
470/* Avoid static vars inside a function since in HPUX they dump as pure. */ 452/* Avoid static vars inside a function since in HPUX they dump as pure. */
471 453
472# ifdef NeXT 454# ifdef NeXT
473static processor_set_t default_set; 455static processor_set_t default_set;
474static int getloadavg_initialized; 456static bool getloadavg_initialized;
475# endif /* NeXT */ 457# endif /* NeXT */
476 458
477# ifdef UMAX 459# ifdef UMAX
@@ -486,8 +468,8 @@ static struct dg_sys_info_load_info load_info; /* what-a-mouthful! */
486# if !defined (HAVE_LIBKSTAT) && defined (LOAD_AVE_TYPE) 468# if !defined (HAVE_LIBKSTAT) && defined (LOAD_AVE_TYPE)
487/* File descriptor open to /dev/kmem or VMS load ave driver. */ 469/* File descriptor open to /dev/kmem or VMS load ave driver. */
488static int channel; 470static int channel;
489/* Nonzero iff channel is valid. */ 471/* True iff channel is valid. */
490static int getloadavg_initialized; 472static bool getloadavg_initialized;
491/* Offset in kmem to seek to read load average, or 0 means invalid. */ 473/* Offset in kmem to seek to read load average, or 0 means invalid. */
492static long offset; 474static long offset;
493 475
@@ -583,7 +565,7 @@ getloadavg (double loadavg[], int nelem)
583 565
584# endif /* hpux && HAVE_PSTAT_GETDYNAMIC */ 566# endif /* hpux && HAVE_PSTAT_GETDYNAMIC */
585 567
586# if !defined (LDAV_DONE) && defined (__linux__) 568# if !defined (LDAV_DONE) && (defined (__linux__) || defined (__CYGWIN__))
587# define LDAV_DONE 569# define LDAV_DONE
588# undef LOAD_AVE_TYPE 570# undef LOAD_AVE_TYPE
589 571
@@ -591,32 +573,36 @@ getloadavg (double loadavg[], int nelem)
591# define LINUX_LDAV_FILE "/proc/loadavg" 573# define LINUX_LDAV_FILE "/proc/loadavg"
592# endif 574# endif
593 575
594 char ldavgbuf[40]; 576 char ldavgbuf[3 * (INT_STRLEN_BOUND (int) + sizeof ".00 ")];
595 double load_ave[3]; 577 char const *ptr = ldavgbuf;
596 int fd, count; 578 int fd, count;
597 579
598 fd = open (LINUX_LDAV_FILE, O_RDONLY); 580 fd = open (LINUX_LDAV_FILE, O_RDONLY);
599 if (fd == -1) 581 if (fd == -1)
600 return -1; 582 return -1;
601 count = read (fd, ldavgbuf, 40); 583 count = read (fd, ldavgbuf, sizeof ldavgbuf - 1);
602 (void) close (fd); 584 (void) close (fd);
603 if (count <= 0) 585 if (count <= 0)
604 return -1; 586 return -1;
587 ldavgbuf[count] = '\0';
605 588
606 /* The following sscanf must use the C locale. */ 589 for (elem = 0; elem < nelem; elem++)
607 setlocale (LC_NUMERIC, "C"); 590 {
608 count = sscanf (ldavgbuf, "%lf %lf %lf", 591 char *endptr;
609 &load_ave[0], &load_ave[1], &load_ave[2]); 592 double d = c_strtod (ptr, &endptr);
610 setlocale (LC_NUMERIC, ""); 593 if (ptr == endptr)
611 if (count < 1) 594 {
612 return -1; 595 if (elem == 0)
613 596 return -1;
614 for (elem = 0; elem < nelem && elem < count; elem++) 597 break;
615 loadavg[elem] = load_ave[elem]; 598 }
599 loadavg[elem] = d;
600 ptr = endptr;
601 }
616 602
617 return elem; 603 return elem;
618 604
619# endif /* __linux__ */ 605# endif /* __linux__ || __CYGWIN__ */
620 606
621# if !defined (LDAV_DONE) && defined (__NetBSD__) 607# if !defined (LDAV_DONE) && defined (__NetBSD__)
622# define LDAV_DONE 608# define LDAV_DONE
@@ -653,7 +639,7 @@ getloadavg (double loadavg[], int nelem)
653 639
654 host_t host; 640 host_t host;
655 struct processor_set_basic_info info; 641 struct processor_set_basic_info info;
656 unsigned info_count; 642 unsigned int info_count;
657 643
658 /* We only know how to get the 1-minute average for this system, 644 /* We only know how to get the 1-minute average for this system,
659 so even if the caller asks for more than 1, we only return 1. */ 645 so even if the caller asks for more than 1, we only return 1. */
@@ -661,7 +647,7 @@ getloadavg (double loadavg[], int nelem)
661 if (!getloadavg_initialized) 647 if (!getloadavg_initialized)
662 { 648 {
663 if (processor_set_default (host_self (), &default_set) == KERN_SUCCESS) 649 if (processor_set_default (host_self (), &default_set) == KERN_SUCCESS)
664 getloadavg_initialized = 1; 650 getloadavg_initialized = true;
665 } 651 }
666 652
667 if (getloadavg_initialized) 653 if (getloadavg_initialized)
@@ -670,7 +656,7 @@ getloadavg (double loadavg[], int nelem)
670 if (processor_set_info (default_set, PROCESSOR_SET_BASIC_INFO, &host, 656 if (processor_set_info (default_set, PROCESSOR_SET_BASIC_INFO, &host,
671 (processor_set_info_t) &info, &info_count) 657 (processor_set_info_t) &info, &info_count)
672 != KERN_SUCCESS) 658 != KERN_SUCCESS)
673 getloadavg_initialized = 0; 659 getloadavg_initialized = false;
674 else 660 else
675 { 661 {
676 if (nelem > 0) 662 if (nelem > 0)
@@ -831,7 +817,7 @@ getloadavg (double loadavg[], int nelem)
831 /* VMS specific code -- read from the Load Ave driver. */ 817 /* VMS specific code -- read from the Load Ave driver. */
832 818
833 LOAD_AVE_TYPE load_ave[3]; 819 LOAD_AVE_TYPE load_ave[3];
834 static int getloadavg_initialized = 0; 820 static bool getloadavg_initialized;
835# ifdef eunice 821# ifdef eunice
836 struct 822 struct
837 { 823 {
@@ -851,7 +837,7 @@ getloadavg (double loadavg[], int nelem)
851 $DESCRIPTOR (descriptor, "LAV0:"); 837 $DESCRIPTOR (descriptor, "LAV0:");
852# endif 838# endif
853 if (sys$assign (&descriptor, &channel, 0, 0) & 1) 839 if (sys$assign (&descriptor, &channel, 0, 0) & 1)
854 getloadavg_initialized = 1; 840 getloadavg_initialized = true;
855 } 841 }
856 842
857 /* Read the load average vector. */ 843 /* Read the load average vector. */
@@ -860,7 +846,7 @@ getloadavg (double loadavg[], int nelem)
860 load_ave, 12, 0, 0, 0, 0) & 1)) 846 load_ave, 12, 0, 0, 0, 0) & 1))
861 { 847 {
862 sys$dassgn (channel); 848 sys$dassgn (channel);
863 getloadavg_initialized = 0; 849 getloadavg_initialized = false;
864 } 850 }
865 851
866 if (!getloadavg_initialized) 852 if (!getloadavg_initialized)
@@ -913,7 +899,7 @@ getloadavg (double loadavg[], int nelem)
913 899
914 ldav_off = sysmp (MP_KERNADDR, MPKA_AVENRUN); 900 ldav_off = sysmp (MP_KERNADDR, MPKA_AVENRUN);
915 if (ldav_off != -1) 901 if (ldav_off != -1)
916 offset = (long) ldav_off & 0x7fffffff; 902 offset = (long int) ldav_off & 0x7fffffff;
917# endif /* sgi */ 903# endif /* sgi */
918 } 904 }
919 905
@@ -921,13 +907,13 @@ getloadavg (double loadavg[], int nelem)
921 if (!getloadavg_initialized) 907 if (!getloadavg_initialized)
922 { 908 {
923# ifndef SUNOS_5 909# ifndef SUNOS_5
924 channel = open ("/dev/kmem", 0); 910 channel = open ("/dev/kmem", O_RDONLY);
925 if (channel >= 0) 911 if (channel >= 0)
926 { 912 {
927 /* Set the channel to close on exec, so it does not 913 /* Set the channel to close on exec, so it does not
928 litter any child's descriptor table. */ 914 litter any child's descriptor table. */
929 set_cloexec_flag (channel, true); 915 set_cloexec_flag (channel, true);
930 getloadavg_initialized = 1; 916 getloadavg_initialized = true;
931 } 917 }
932# else /* SUNOS_5 */ 918# else /* SUNOS_5 */
933 /* We pass 0 for the kernel, corefile, and swapfile names 919 /* We pass 0 for the kernel, corefile, and swapfile names
@@ -938,7 +924,7 @@ getloadavg (double loadavg[], int nelem)
938 /* nlist the currently running kernel. */ 924 /* nlist the currently running kernel. */
939 kvm_nlist (kd, nl); 925 kvm_nlist (kd, nl);
940 offset = nl[0].n_value; 926 offset = nl[0].n_value;
941 getloadavg_initialized = 1; 927 getloadavg_initialized = true;
942 } 928 }
943# endif /* SUNOS_5 */ 929# endif /* SUNOS_5 */
944 } 930 }
@@ -953,14 +939,14 @@ getloadavg (double loadavg[], int nelem)
953 != sizeof (load_ave)) 939 != sizeof (load_ave))
954 { 940 {
955 close (channel); 941 close (channel);
956 getloadavg_initialized = 0; 942 getloadavg_initialized = false;
957 } 943 }
958# else /* SUNOS_5 */ 944# else /* SUNOS_5 */
959 if (kvm_read (kd, offset, (char *) load_ave, sizeof (load_ave)) 945 if (kvm_read (kd, offset, (char *) load_ave, sizeof (load_ave))
960 != sizeof (load_ave)) 946 != sizeof (load_ave))
961 { 947 {
962 kvm_close (kd); 948 kvm_close (kd);
963 getloadavg_initialized = 0; 949 getloadavg_initialized = false;
964 } 950 }
965# endif /* SUNOS_5 */ 951# endif /* SUNOS_5 */
966 } 952 }
@@ -980,20 +966,19 @@ getloadavg (double loadavg[], int nelem)
980# define LDAV_DONE 966# define LDAV_DONE
981# endif /* !LDAV_DONE && LOAD_AVE_TYPE */ 967# endif /* !LDAV_DONE && LOAD_AVE_TYPE */
982 968
983# ifdef LDAV_DONE 969# if !defined LDAV_DONE
984 return elem;
985# else
986 /* Set errno to zero to indicate that there was no particular error; 970 /* Set errno to zero to indicate that there was no particular error;
987 this function just can't work at all on this system. */ 971 this function just can't work at all on this system. */
988 errno = 0; 972 errno = 0;
989 return -1; 973 elem = -1;
990# endif 974# endif
975 return elem;
991} 976}
992 977
993#endif /* ! HAVE_GETLOADAVG */ 978#endif /* ! HAVE_GETLOADAVG */
994 979
995#ifdef TEST 980#ifdef TEST
996void 981int
997main (int argc, char **argv) 982main (int argc, char **argv)
998{ 983{
999 int naptime = 0; 984 int naptime = 0;
@@ -1011,7 +996,7 @@ main (int argc, char **argv)
1011 if (loads == -1) 996 if (loads == -1)
1012 { 997 {
1013 perror ("Error getting load average"); 998 perror ("Error getting load average");
1014 exit (1); 999 return EXIT_FAILURE;
1015 } 1000 }
1016 if (loads > 0) 1001 if (loads > 0)
1017 printf ("1-minute: %f ", avg[0]); 1002 printf ("1-minute: %f ", avg[0]);
@@ -1027,6 +1012,6 @@ main (int argc, char **argv)
1027 sleep (naptime); 1012 sleep (naptime);
1028 } 1013 }
1029 1014
1030 exit (0); 1015 return EXIT_SUCCESS;
1031} 1016}
1032#endif /* TEST */ 1017#endif /* TEST */