xref: /original-bsd/lib/libc/gen/getloadavg.c (revision 48611f03)
1 /*-
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #if defined(LIBC_SCCS) && !defined(lint)
9 static char sccsid[] = "@(#)getloadavg.c	6.4 (Berkeley) 03/31/93";
10 #endif /* LIBC_SCCS and not lint */
11 
12 #include <sys/param.h>
13 #include <sys/types.h>
14 #include <sys/file.h>
15 #include <sys/kernel.h>
16 #include <sys/sysctl.h>
17 #include <vm/vm_param.h>
18 #include <nlist.h>
19 
20 static struct nlist nl[] = {
21 	{ "_averunnable" },
22 #define	X_AVERUNNABLE	0
23 	{ "_fscale" },
24 #define	X_FSCALE	1
25 	{ "" },
26 };
27 
28 /*
29  *  getloadavg() -- Get system load averages.
30  *
31  *  Put `nelem' samples into `loadavg' array.
32  *  Return number of samples retrieved, or -1 on error.
33  */
34 getloadavg(loadavg, nelem)
35 	double loadavg[];
36 	int nelem;
37 {
38 	static int need_nlist = 1;
39 	struct loadavg loadinfo;
40 	int size, kmemfd, i;
41 	int alreadyopen = 1;
42 	int mib[2], fscale;
43 
44 	size = sizeof(loadinfo);
45 	mib[0] = CTL_VM;
46 	mib[1] = VM_LOADAVG;
47 	if (sysctl(mib, 2, &loadinfo, &size, NULL, 0) < 0) {
48 		if ((alreadyopen = kvm_openfiles(NULL, NULL, NULL)) == -1)
49 			return (-1);
50 		/*
51 		 * cache nlist
52 		 */
53 		if (need_nlist) {
54 			if (kvm_nlist(nl) != 0)
55 				goto bad;
56 			need_nlist = 0;
57 		}
58 		if (kvm_read((off_t)nl[X_AVERUNNABLE].n_value,
59 		    (char *)&loadinfo, sizeof(loadinfo)) != size)
60 			goto bad;
61 		/*
62 		 * Old kernel have fscale separately; if not found assume
63 		 * running new format.
64 		 */
65 		if (kvm_read( (off_t)nl[X_FSCALE].n_value, (char *)&fscale,
66 		    sizeof(fscale)) == sizeof(fscale))
67 			loadinfo.fscale = fscale;
68 	}
69 	nelem = MIN(nelem, sizeof(loadinfo.ldavg) / sizeof(fixpt_t));
70 	for (i = 0; i < nelem; i++)
71 		loadavg[i] = (double) loadinfo.ldavg[i] / loadinfo.fscale;
72 	if (!alreadyopen)
73 		kvm_close();
74 	return (nelem);
75 
76 bad:
77 	if (!alreadyopen)
78 		kvm_close();
79 	return (-1);
80 }
81