diff options
Diffstat (limited to 'lib/getloadavg.c')
| -rw-r--r-- | lib/getloadavg.c | 149 |
1 files changed, 67 insertions, 82 deletions
diff --git a/lib/getloadavg.c b/lib/getloadavg.c index c6b6fee1..2a501314 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 | ||
| 107 | extern 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 |
| 473 | static processor_set_t default_set; | 455 | static processor_set_t default_set; |
| 474 | static int getloadavg_initialized; | 456 | static 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. */ |
| 488 | static int channel; | 470 | static int channel; |
| 489 | /* Nonzero iff channel is valid. */ | 471 | /* True iff channel is valid. */ |
| 490 | static int getloadavg_initialized; | 472 | static 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. */ |
| 492 | static long offset; | 474 | static 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 |
| 996 | void | 981 | int |
| 997 | main (int argc, char **argv) | 982 | main (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 */ |
