Add 'getidle' CPU utilization measurement infrastructure

This commit is contained in:
David van Moolenbroek
2009-12-02 11:52:26 +00:00
parent be2087ecf9
commit fce9fd4b4e
22 changed files with 190 additions and 31 deletions

View File

@@ -10,6 +10,7 @@ libsys_FILES=" \
kputc.c \
tickdelay.c \
get_randomness.c \
getidle.c \
getuptime.c \
getuptime2.c \
env_get_prm.c \

92
lib/sysutil/getidle.c Normal file
View File

@@ -0,0 +1,92 @@
/* getidle.c - by David van Moolenbroek <dcvmoole@cs.vu.nl> */
/* Usage:
*
* double idleperc;
* getidle();
* ...
* idleperc = getidle();
* printf("CPU usage: %lg%%\n", 100.0 - idleperc);
*
* This routine goes through PM to get the idle time, rather than making the
* sys_getinfo() call to the kernel directly. This means that it can be used
* by non-system processes as well, but it will incur some extra overhead in
* the system case. The overhead does not end up being measured, because the
* system is clearly not idle while the system calls are being made. In any
* case, for this reason, only one getidle() run is allowed at a time.
*
* Note that the kernel has to be compiled with CONFIG_IDLE_TSC support.
*/
#define _MINIX 1
#define _SYSTEM 1
#include <minix/sysinfo.h>
#include <minix/u64.h>
#include <minix/sysutil.h>
static u64_t start, idle;
static int running = 0;
static double make_double(u64_t d)
{
/* Convert a 64-bit fixed point value into a double.
* This whole thing should be replaced by something better eventually.
*/
double value;
int i;
value = (double) ex64hi(d);
for (i = 0; i < sizeof(unsigned long); i += 2)
value *= 65536.0;
value += (double) ex64lo(d);
return value;
}
double getidle(void)
{
u64_t stop, idle2;
u64_t idelta, tdelta;
double ifp, tfp, rfp;
int r;
if (!running) {
r = getsysinfo_up(PM_PROC_NR, SIU_IDLETSC, sizeof(idle), &idle);
if (r != sizeof(idle))
return -1.0;
running = 1;
read_tsc_64(&start);
return 0.0;
}
else {
read_tsc_64(&stop);
running = 0;
r = getsysinfo_up(PM_PROC_NR, SIU_IDLETSC, sizeof(idle2), &idle2);
if (r != sizeof(idle2))
return -1.0;
idelta = sub64(idle2, idle);
tdelta = sub64(stop, start);
if (cmp64(idelta, tdelta) >= 0)
return 100.0;
ifp = make_double(idelta);
tfp = make_double(tdelta);
rfp = ifp / tfp * 100.0;
if (rfp < 0.0) rfp = 0.0;
else if (rfp > 100.0) rfp = 100.0;
return rfp;
}
running = !running;
}

View File

@@ -16,7 +16,7 @@
#include <stdlib.h>
#include <string.h>
#include <minix/profile.h>
#include <minix/syslib.h>
#include <minix/sysutil.h>
#include <minix/u64.h>
PRIVATE char cpath[CPROF_CPATH_MAX_LEN]; /* current call path string */
@@ -61,7 +61,7 @@ char *name;
if (cprof_locked) return; else cprof_locked = 1;
/* Read CPU cycle count into local variable. */
read_tsc(&start.hi, &start.lo);
read_tsc_64(&start);
/* Run init code once after system boot. */
if (init == 0) {
@@ -105,8 +105,7 @@ char *name;
}
/* Save initial cycle count on stack. */
cprof_stk[cprof_stk_top].start_1.hi = start.hi;
cprof_stk[cprof_stk_top].start_1.lo = start.lo;
cprof_stk[cprof_stk_top].start_1 = start;
/* Check available call path len. */
if (cpath_len + strlen(name) + 1 > CPROF_CPATH_MAX_LEN) {
@@ -167,8 +166,7 @@ char *name;
cprof_stk[cprof_stk_top].slot = cprof_slot;
/* Again save CPU cycle count on stack. */
read_tsc(&cprof_stk[cprof_stk_top].start_2.hi,
&cprof_stk[cprof_stk_top].start_2.lo);
read_tsc_64(&cprof_stk[cprof_stk_top].start_2);
cprof_locked = 0;
}
@@ -201,8 +199,7 @@ char *name;
sub64(spent, cprof_stk[cprof_stk_top].spent_deeper));
/* Clear spent_deeper for call level we're leaving. */
cprof_stk[cprof_stk_top].spent_deeper.lo = 0;
cprof_stk[cprof_stk_top].spent_deeper.hi = 0;
cprof_stk[cprof_stk_top].spent_deeper = cvu64(0);
/* Adjust call path string and stack. */
cpath_len = cprof_stk[cprof_stk_top].cpath_len;
@@ -246,12 +243,9 @@ PRIVATE void cprof_init() {
for (i=0; i<CPROF_STACK_SIZE; i++) {
cprof_stk[i].cpath_len = 0;
cprof_stk[i].slot = 0;
cprof_stk[i].start_1.lo = 0;
cprof_stk[i].start_1.hi = 0;
cprof_stk[i].start_2.lo = 0;
cprof_stk[i].start_2.hi = 0;
cprof_stk[i].spent_deeper.lo = 0;
cprof_stk[i].spent_deeper.hi = 0;
cprof_stk[i].start_1 = cvu64(0);
cprof_stk[i].start_2 = cvu64(0);
cprof_stk[i].spent_deeper = cvu64(0);
}
}