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