xref: /minix3/minix/lib/libsys/arch/i386/getidle.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1*433d6423SLionel Sambuc /* getidle.c - by David van Moolenbroek <dcvmoole@cs.vu.nl> */
2*433d6423SLionel Sambuc 
3*433d6423SLionel Sambuc /* Usage:
4*433d6423SLionel Sambuc  *
5*433d6423SLionel Sambuc  *   double idleperc;
6*433d6423SLionel Sambuc  *   getidle();
7*433d6423SLionel Sambuc  *   ...
8*433d6423SLionel Sambuc  *   idleperc = getidle();
9*433d6423SLionel Sambuc  *   if (idleperc >= 0.0)
10*433d6423SLionel Sambuc  *     printf("CPU usage: %lg%%\n", 100.0 - idleperc);
11*433d6423SLionel Sambuc  *
12*433d6423SLionel Sambuc  * Notes:
13*433d6423SLionel Sambuc  * - This functionality can only be used by system processes.
14*433d6423SLionel Sambuc  * - Only one getidle() run is allowed per process at a time.
15*433d6423SLionel Sambuc  *
16*433d6423SLionel Sambuc  */
17*433d6423SLionel Sambuc 
18*433d6423SLionel Sambuc #define _SYSTEM		1
19*433d6423SLionel Sambuc #include <lib.h>
20*433d6423SLionel Sambuc #include <minix/u64.h>
21*433d6423SLionel Sambuc #include <minix/sysutil.h>
22*433d6423SLionel Sambuc #include <minix/syslib.h>
23*433d6423SLionel Sambuc #include <minix/minlib.h>
24*433d6423SLionel Sambuc 
25*433d6423SLionel Sambuc static u64_t start, idle;
26*433d6423SLionel Sambuc static int running = 0;
27*433d6423SLionel Sambuc 
make_double(u64_t d)28*433d6423SLionel Sambuc static double make_double(u64_t d)
29*433d6423SLionel Sambuc {
30*433d6423SLionel Sambuc /* Convert a 64-bit fixed point value into a double.
31*433d6423SLionel Sambuc  * This whole thing should be replaced by something better eventually.
32*433d6423SLionel Sambuc  */
33*433d6423SLionel Sambuc   double value;
34*433d6423SLionel Sambuc   size_t i;
35*433d6423SLionel Sambuc 
36*433d6423SLionel Sambuc   value = (double) ex64hi(d);
37*433d6423SLionel Sambuc   for (i = 0; i < sizeof(unsigned long); i += 2)
38*433d6423SLionel Sambuc 	value *= 65536.0;
39*433d6423SLionel Sambuc 
40*433d6423SLionel Sambuc   value += (double) ex64lo(d);
41*433d6423SLionel Sambuc 
42*433d6423SLionel Sambuc   return value;
43*433d6423SLionel Sambuc }
44*433d6423SLionel Sambuc 
getidle(void)45*433d6423SLionel Sambuc double getidle(void)
46*433d6423SLionel Sambuc {
47*433d6423SLionel Sambuc   u64_t stop, idle2;
48*433d6423SLionel Sambuc   u64_t idelta, tdelta;
49*433d6423SLionel Sambuc   double ifp, tfp, rfp;
50*433d6423SLionel Sambuc   int r;
51*433d6423SLionel Sambuc 
52*433d6423SLionel Sambuc   if (!running) {
53*433d6423SLionel Sambuc 	if ((r = sys_getidletsc(&idle)) != OK)
54*433d6423SLionel Sambuc 		return -1.0;
55*433d6423SLionel Sambuc 
56*433d6423SLionel Sambuc 	running = 1;
57*433d6423SLionel Sambuc 
58*433d6423SLionel Sambuc 	read_tsc_64(&start);
59*433d6423SLionel Sambuc 
60*433d6423SLionel Sambuc 	return 0.0;
61*433d6423SLionel Sambuc   }
62*433d6423SLionel Sambuc   else {
63*433d6423SLionel Sambuc 	read_tsc_64(&stop);
64*433d6423SLionel Sambuc 
65*433d6423SLionel Sambuc 	running = 0;
66*433d6423SLionel Sambuc 
67*433d6423SLionel Sambuc 	if ((r = sys_getidletsc(&idle2)) != OK)
68*433d6423SLionel Sambuc 		return -1.0;
69*433d6423SLionel Sambuc 
70*433d6423SLionel Sambuc 	idelta = idle2 - idle;
71*433d6423SLionel Sambuc 	tdelta = stop - start;
72*433d6423SLionel Sambuc 
73*433d6423SLionel Sambuc 	if (idelta >= tdelta)
74*433d6423SLionel Sambuc 		return 100.0;
75*433d6423SLionel Sambuc 
76*433d6423SLionel Sambuc 	ifp = make_double(idelta);
77*433d6423SLionel Sambuc 	tfp = make_double(tdelta);
78*433d6423SLionel Sambuc 
79*433d6423SLionel Sambuc 	rfp = ifp / tfp * 100.0;
80*433d6423SLionel Sambuc 
81*433d6423SLionel Sambuc 	if (rfp < 0.0) rfp = 0.0;
82*433d6423SLionel Sambuc 	else if (rfp > 100.0) rfp = 100.0;
83*433d6423SLionel Sambuc 
84*433d6423SLionel Sambuc 	return rfp;
85*433d6423SLionel Sambuc   }
86*433d6423SLionel Sambuc }
87