diff --git a/src/domain.c b/src/domain.c index 1e2ba889a9521ecbc9daa6413b659535b9d54369..ae80aa75f27d9cdf73e7c43ae0c705434df09eb4 100644 --- a/src/domain.c +++ b/src/domain.c @@ -48,11 +48,38 @@ static struct domain *add_domains(struct domain_list *list) return &(list->domains[list->num - 1]); } +static void copy_domains(struct domain_list *now, struct domain_list *pre) +{ + if (pre->domains) { + free(pre->domains); + } + pre->num = now->num; + pre->domains = malloc(sizeof(struct domain) * pre->num); + if (pre->domains == NULL) { + pre->num = 0; + return; + } + memcpy(pre->domains, now->domains, sizeof(struct domain) * pre->num); +} + static void pop_domains(struct domain_list *list) { list->num--; } +/* + * get domain from domain list + */ +static struct domain *get_domain_from_id(int id, struct domain_list *list) +{ + for (int i = 0; i < list->num; i++) { + if (list->domains[i].domain_id == id) { + return &(list->domains[i]); + } + } + return NULL; +} + static int get_id_from_cgroup(pid_t pid) { char path[CGROUP_PATH_SIZE]; @@ -92,7 +119,7 @@ static int set_domain(struct domain *dom, const char *name) char path[PATH_MAX]; char pid[PID_STRING_MAX]; char *end = NULL; - + if (len >= DOMAIN_NAME_MAX - 1) { return -1; } @@ -160,12 +187,23 @@ static int get_qemu_id(struct domain_list *list) return list->num; } -int refresh_domains(struct domain_list *list) +int refresh_domains(struct domain_list *now, struct domain_list *pre) { int num; - init_domains(list); - num = get_qemu_id(list); + copy_domains(now, pre); /* save last data int pre */ + init_domains(now); + num = get_qemu_id(now); + + for (int i = 0; i < now->num; i++) { + int id = now->domains[i].domain_id; + struct domain *old_domain = get_domain_from_id(id, pre); + + if (old_domain == NULL) { + continue; + } + refresh_delta_stat(&(now->domains[i]), old_domain); + } return num; } diff --git a/src/domain.h b/src/domain.h index 12b6f9468c3b5efd61fff80ea251146b3e78838d..48e99666fd4bfb463eeab975021961c64519721c 100644 --- a/src/domain.h +++ b/src/domain.h @@ -21,5 +21,5 @@ struct domain_list { int num; }; -int refresh_domains(struct domain_list *list); +int refresh_domains(struct domain_list *now, struct domain_list *pre); #endif diff --git a/src/field.c b/src/field.c index 62e51ad7054df756f4542d21d07e87bdbbcfded4..f3b2d896ca1edb8a8e3dc03267e974b70d0c58fe 100644 --- a/src/field.c +++ b/src/field.c @@ -26,6 +26,7 @@ FID fields[] = { {"VMname", FIELDS_DISPLAY, 14 }, {"DID", FIELDS_DISPLAY, 5 }, {"PID", FIELDS_DISPLAY, 8 }, + {"%CPU", FIELDS_DISPLAY, 5 }, {"S", FIELDS_DISPLAY, 5 }, {"P", FIELDS_DISPLAY, 5 } }; diff --git a/src/field.h b/src/field.h index 687ac7f207c2370af4b5c12bc0f472d8cabc39d2..495f55040c94fca27c4cf73cdb473dfaba79fae6 100644 --- a/src/field.h +++ b/src/field.h @@ -20,6 +20,7 @@ enum fields_type { FD_VMNAME, FD_DID, FD_PID, + FD_CPU, FD_STATE, FD_P, FD_END diff --git a/src/proc.c b/src/proc.c index 5efb9a1edfdde2575c7038d1aaf20507e6831c67..d46204dba487f9afa74a5fc10e859b3fdac7b14c 100644 --- a/src/proc.c +++ b/src/proc.c @@ -19,7 +19,8 @@ #define STAT_PATH_SIZE 40 struct file_item proc_stab[] = { -#define GF(f) (DFUN_T)GET_NAME(f) +#define GDF(f) (void *)GET_NAME(f), (void *)DELTA_NAME(f) +#define GF(f) (void *)GET_NAME(f), NULL {"%c", GF(state)}, {"%d", GF(ppid)}, {"%d", GF(pgrd)}, @@ -31,8 +32,8 @@ struct file_item proc_stab[] = { {"%lu", GF(cmin_flt)}, {"%lu", GF(maj_flt)}, {"%lu", GF(cmaj_flt)}, - {"%llu", GF(utime)}, - {"%llu", GF(stime)}, + {"%llu", GDF(utime)}, + {"%llu", GDF(stime)}, {"%llu", GF(cutime)}, {"%llu", GF(cstime)}, {"%ld", GF(priority)}, @@ -48,18 +49,19 @@ struct file_item proc_stab[] = { {"%lu", GF(start_stack)}, {"%lu", GF(kstk_esp)}, {"%lu", GF(kstk_eip)}, - {"%*s", NULL}, /* discard signal */ - {"%*s", NULL}, /* discard blocked */ - {"%*s", NULL}, /* discard sigignore */ - {"%*s", NULL}, /* discard sigcatch */ + {"%*s", NULL, NULL}, /* discard signal */ + {"%*s", NULL, NULL}, /* discard blocked */ + {"%*s", NULL, NULL}, /* discard sigignore */ + {"%*s", NULL, NULL}, /* discard sigcatch */ {"%lu", GF(wchan)}, - {"%*u", NULL}, /* dsicard nswap */ - {"%*u", NULL}, /* discard cnswap */ + {"%*u", NULL, NULL}, /* dsicard nswap */ + {"%*u", NULL, NULL}, /* discard cnswap */ {"%d", GF(exit_signal)}, {"%d", GF(processor)}, {"%lu", GF(rtprio)}, {"%lu", GF(sched)} #undef GF +#undef GDF }; const int stat_size = sizeof(proc_stab) / sizeof(struct file_item); @@ -93,3 +95,12 @@ int get_proc_stat(struct domain *dom) } return 1; } + +void refresh_delta_stat(struct domain *new, struct domain *old) +{ + for (int i = 0; i < stat_size; i++) { + if (proc_stab[i].delta_fun) { + (*proc_stab[i].delta_fun)(new, old); + } + } +} diff --git a/src/proc.h b/src/proc.h index 61ca890a30a8e683e5fc9bb1a993213b841ec8a7..b8e3e556f7427cd370612d40d24022306649708b 100644 --- a/src/proc.h +++ b/src/proc.h @@ -13,39 +13,40 @@ #ifndef SRC_PROC_H #define SRC_PROC_H -GET_FUN(state) -GET_FUN(ppid) -GET_FUN(pgrd) -GET_FUN(session) -GET_FUN(tty) -GET_FUN(tpgid) -GET_FUN(flags) -GET_FUN(min_flt) -GET_FUN(cmin_flt) -GET_FUN(maj_flt) -GET_FUN(cmaj_flt) -GET_FUN(utime) -GET_FUN(stime) -GET_FUN(cutime) -GET_FUN(cstime) -GET_FUN(priority) -GET_FUN(nice) -GET_FUN(nlwp) -GET_FUN(alarm) -GET_FUN(start_time) -GET_FUN(vsize) -GET_FUN(rss) -GET_FUN(rss_rlim) -GET_FUN(start_code) -GET_FUN(end_code) -GET_FUN(start_stack) -GET_FUN(kstk_esp) -GET_FUN(kstk_eip) -GET_FUN(wchan) -GET_FUN(exit_signal) -GET_FUN(processor) -GET_FUN(rtprio) -GET_FUN(sched) +GET_VALUE(state) +GET_VALUE(ppid) +GET_VALUE(pgrd) +GET_VALUE(session) +GET_VALUE(tty) +GET_VALUE(tpgid) +GET_VALUE(flags) +GET_VALUE(min_flt) +GET_VALUE(cmin_flt) +GET_VALUE(maj_flt) +GET_VALUE(cmaj_flt) +GET_DELTA_FUN(utime) +GET_DELTA_FUN(stime) +GET_VALUE(cutime) +GET_VALUE(cstime) +GET_VALUE(priority) +GET_VALUE(nice) +GET_VALUE(nlwp) +GET_VALUE(alarm) +GET_VALUE(start_time) +GET_VALUE(vsize) +GET_VALUE(rss) +GET_VALUE(rss_rlim) +GET_VALUE(start_code) +GET_VALUE(end_code) +GET_VALUE(start_stack) +GET_VALUE(kstk_esp) +GET_VALUE(kstk_eip) +GET_VALUE(wchan) +GET_VALUE(exit_signal) +GET_VALUE(processor) +GET_VALUE(rtprio) +GET_VALUE(sched) int get_proc_stat(struct domain *dom); +void refresh_delta_stat(struct domain *new, struct domain *old); #endif diff --git a/src/type.h b/src/type.h index ca749d9d049b48b1955cc1e32c34a93128717c3a..40dd0047fa500eb6ad3368507439b06370d4ea5a 100644 --- a/src/type.h +++ b/src/type.h @@ -15,9 +15,6 @@ #include -typedef void *(*DFUN_T)(const void *); -typedef void *(DFUN_VOID_T)(void *, void *); - typedef unsigned long long u64; #define DOMAIN_NAME_MAX 256 @@ -27,23 +24,35 @@ typedef unsigned long long u64; #define DFX_VALUE(v) v, DELTA_VALUE(v) #define GET_NAME(v) domain_get_ ## v -#define GET_FUN(v) \ +#define GET_VALUE(v) \ static inline void *GET_NAME(v)(struct domain *dom) \ { \ return (void *)(&(dom->v)); \ } #define GET_DELTA_NAME(v) domain_get_delta_ ## v -#define GET_DELTA_FUN(v) \ +#define GET_DELTA_VALUE(v) \ static inline void *GET_DELTA_NAME(v)(struct domain *dom) \ { \ return (void *)(&(dom->DELTA_VALUE(v))); \ } +#define DELTA_NAME(v) domain_delta_ ## v +#define DELTA_FUN(v) \ + static inline void DELTA_NAME(v)(struct domain *new, \ + struct domain *old) \ + { \ + new->DELTA_VALUE(v) = new->v - old->v; \ + } + +#define GET_DELTA_FUN(v) \ + GET_VALUE(v) \ + DELTA_FUN(v) + struct file_item { const char *format; - DFUN_T get_fun; - DFUN_T delta_fun; + void *(*get_fun)(void *); + void (*delta_fun)(void *, void *); }; struct domain { @@ -83,11 +92,10 @@ struct domain { sched, wchan; u64 - utime, - stime, + DFX_VALUE(utime), + DFX_VALUE(stime), cutime, cstime, start_time; }; - #endif diff --git a/src/vmtop.c b/src/vmtop.c index 6781a68fbd33d91f0233ae6cde5075bea4abd5e2..00ec6b7c9fef12f7994ee7941992f4eea794a2a7 100644 --- a/src/vmtop.c +++ b/src/vmtop.c @@ -26,6 +26,7 @@ int delay_time; int quit_flag; struct domain_list scr_cur; +struct domain_list scr_pre; static void init_screen(void) { @@ -101,6 +102,13 @@ static void print_domain_field(struct domain *dom, int field) printw("%*lu", fields[i].align, dom->pid); break; } + case FD_CPU: { + u64 cpu_jeffies = dom->DELTA_VALUE(utime) + dom->DELTA_VALUE(stime); + double usage = (double)cpu_jeffies * 100 / + sysconf(_SC_CLK_TCK) / delay_time; + printw("%*.1f", fields[i].align, usage); + break; + } case FD_STATE: { printw("%*c", fields[i].align, dom->state); break; @@ -228,7 +236,7 @@ int main(int argc, char *argv[]) delay_time = 1; /* default delay 1s between display*/ do { - refresh_domains(&scr_cur); + refresh_domains(&scr_cur, &scr_pre); /* display frame make */ move(0, 0);