xref: /original-bsd/lib/libc/gen/getloadavg.c (revision d1f811c7)
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.3 (Berkeley) 02/25/92";
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/kinfo.h>
17 #include <nlist.h>
18 
19 static struct nlist nl[] = {
20 	{ "_averunnable" },
21 #define	X_AVERUNNABLE	0
22 	{ "_fscale" },
23 #define	X_FSCALE	1
24 	{ "" },
25 };
26 
27 /*
28  *  getloadavg() -- Get system load averages.
29  *
30  *  Put `nelem' samples into `loadavg' array.
31  *  Return number of samples retrieved, or -1 on error.
32  */
33 getloadavg(loadavg, nelem)
34 	double loadavg[];
35 	int nelem;
36 {
37 	static int need_nlist = 1;
38 	struct loadavg loadinfo;
39 	int size, kmemfd, i;
40 	int alreadyopen = 1;
41 	int fscale;
42 
43 	size = sizeof(loadinfo);
44 	if (getkerninfo(KINFO_LOADAVG, &loadinfo, &size, 0) < 0) {
45 		if ((alreadyopen = kvm_openfiles(NULL, NULL, NULL)) == -1)
46 			return (-1);
47 		/*
48 		 * cache nlist
49 		 */
50 		if (need_nlist) {
51 			if (kvm_nlist(nl) != 0)
52 				goto bad;
53 			need_nlist = 0;
54 		}
55 		if (kvm_read((off_t)nl[X_AVERUNNABLE].n_value,
56 		    (char *)&loadinfo, sizeof(loadinfo)) != size)
57 			goto bad;
58 		/*
59 		 * Old kernel have fscale separately; if not found assume
60 		 * running new format.
61 		 */
62 		if (kvm_read( (off_t)nl[X_FSCALE].n_value, (char *)&fscale,
63 		    sizeof(fscale)) == sizeof(fscale))
64 			loadinfo.fscale = fscale;
65 	}
66 	nelem = MIN(nelem, sizeof(loadinfo.ldavg) / sizeof(fixpt_t));
67 	for (i = 0; i < nelem; i++)
68 		loadavg[i] = (double) loadinfo.ldavg[i] / loadinfo.fscale;
69 	if (!alreadyopen)
70 		kvm_close();
71 	return (nelem);
72 
73 bad:
74 	if (!alreadyopen)
75 		kvm_close();
76 	return (-1);
77 }
78