root/lib/getloadavg.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. getloadavg

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

/* [<][>][^][v][top][bottom][index][help] */