root/maint/gnulib/lib/getloadavg.c

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

/* [previous][next][first][last][top][bottom][index][help] */