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