xref: /csrg-svn/lib/libc/gen/getloadavg.c (revision 58899)
144571Smarc /*-
238184Smckusick  * Copyright (c) 1989 The Regents of the University of California.
338184Smckusick  * All rights reserved.
438184Smckusick  *
544571Smarc  * %sccs.include.redist.c%
638184Smckusick  */
738184Smckusick 
838184Smckusick #if defined(LIBC_SCCS) && !defined(lint)
9*58899Smckusick static char sccsid[] = "@(#)getloadavg.c	6.4 (Berkeley) 03/31/93";
1044571Smarc #endif /* LIBC_SCCS and not lint */
1138184Smckusick 
1238184Smckusick #include <sys/param.h>
1338184Smckusick #include <sys/types.h>
1438184Smckusick #include <sys/file.h>
1552663Smckusick #include <sys/kernel.h>
16*58899Smckusick #include <sys/sysctl.h>
17*58899Smckusick #include <vm/vm_param.h>
1838184Smckusick #include <nlist.h>
1938184Smckusick 
2038184Smckusick static struct nlist nl[] = {
2138184Smckusick 	{ "_averunnable" },
2238184Smckusick #define	X_AVERUNNABLE	0
2338184Smckusick 	{ "_fscale" },
2438184Smckusick #define	X_FSCALE	1
2538184Smckusick 	{ "" },
2638184Smckusick };
2738184Smckusick 
2838184Smckusick /*
2938184Smckusick  *  getloadavg() -- Get system load averages.
3038184Smckusick  *
3138184Smckusick  *  Put `nelem' samples into `loadavg' array.
3238184Smckusick  *  Return number of samples retrieved, or -1 on error.
3338184Smckusick  */
3438184Smckusick getloadavg(loadavg, nelem)
3538184Smckusick 	double loadavg[];
3638184Smckusick 	int nelem;
3738184Smckusick {
3838184Smckusick 	static int need_nlist = 1;
3952663Smckusick 	struct loadavg loadinfo;
4052663Smckusick 	int size, kmemfd, i;
4152663Smckusick 	int alreadyopen = 1;
42*58899Smckusick 	int mib[2], fscale;
4338184Smckusick 
4452663Smckusick 	size = sizeof(loadinfo);
45*58899Smckusick 	mib[0] = CTL_VM;
46*58899Smckusick 	mib[1] = VM_LOADAVG;
47*58899Smckusick 	if (sysctl(mib, 2, &loadinfo, &size, NULL, 0) < 0) {
4852663Smckusick 		if ((alreadyopen = kvm_openfiles(NULL, NULL, NULL)) == -1)
4952663Smckusick 			return (-1);
5052663Smckusick 		/*
5152663Smckusick 		 * cache nlist
5252663Smckusick 		 */
5352663Smckusick 		if (need_nlist) {
5452663Smckusick 			if (kvm_nlist(nl) != 0)
5552663Smckusick 				goto bad;
5652663Smckusick 			need_nlist = 0;
5752663Smckusick 		}
5852663Smckusick 		if (kvm_read((off_t)nl[X_AVERUNNABLE].n_value,
5952663Smckusick 		    (char *)&loadinfo, sizeof(loadinfo)) != size)
6044571Smarc 			goto bad;
6152663Smckusick 		/*
6252663Smckusick 		 * Old kernel have fscale separately; if not found assume
6352663Smckusick 		 * running new format.
6452663Smckusick 		 */
6552663Smckusick 		if (kvm_read( (off_t)nl[X_FSCALE].n_value, (char *)&fscale,
6652663Smckusick 		    sizeof(fscale)) == sizeof(fscale))
6752663Smckusick 			loadinfo.fscale = fscale;
6838184Smckusick 	}
6952663Smckusick 	nelem = MIN(nelem, sizeof(loadinfo.ldavg) / sizeof(fixpt_t));
7038184Smckusick 	for (i = 0; i < nelem; i++)
7152663Smckusick 		loadavg[i] = (double) loadinfo.ldavg[i] / loadinfo.fscale;
7244571Smarc 	if (!alreadyopen)
7344571Smarc 		kvm_close();
7438184Smckusick 	return (nelem);
7538184Smckusick 
7638184Smckusick bad:
7744571Smarc 	if (!alreadyopen)
7844571Smarc 		kvm_close();
7938184Smckusick 	return (-1);
8038184Smckusick }
81