getloadavg.c 26 KB

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