Files
mckernel/tools/mcstat/mcstat.c
2018-03-09 14:31:07 +09:00

275 lines
6.8 KiB
C

/*
* mcstat -- reports McKernel statistis
* mcstat [-h]
* mcstat [-n] [delay [ count]]
* mcstat [-s]
* mcstat [-c]
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <ihk/ihk_host_user.h>
#include <ihk/ihklib_private.h> // mcctrl_ioctl_getrusage_desc is defined here
#undef IHK_MAX_NUM_NUMA_NODES
#include <ihklib_rusage.h> // mckernel_rusage is defined here
#define MAX_CPUS 256
#define MiB100 (100*1024*1024) // 100 MiB
#define MiB (1024*1024)
#define GiB (1024*1024*1024)
#define CONV_UNIT(d) (((float)(d))/scale)
#define UPDATE_COUNTER(c) (c = (c + 1) % 10)
struct mckernel_rusage rbuf;
static void mcstatistics(int idx, int once, int delay, int count);
static void mcstatus(int idx, int delay, int count);
static void mcosusage(int idx, int once, int delay, int count);
static void
usage()
{
fprintf(stderr, "Usage: mcstat [-h|-n|-s] [delay [count]]\n");
}
int
main(int argc, char **argv)
{
int opt;
int idx = 0; /* index of OS instance */
int sflag = 0; /* statistic option */
int cflag = 0; /* cpu info */
int once = 0; /* header is shown once */
int delay = 0; /* delay in second */
int count = 1; /* */
if (argc > 1) {
while ((opt = getopt(argc, argv, "chns")) != -1) {
switch (opt) {
case 'c': /* cpu info */
cflag = 1; break;
case 'h':
usage(); exit(0);
case 'n':
once = 1; break;
case 's': /* status */
sflag = 1; break;
}
}
}
if (optind < argc) { /* interval */
delay = atoi(argv[optind]);
if (optind + 1 < argc) { /* count */
count = atoi(argv[optind+1]);
} else {
count = -1; /* inifi */
}
}
if (sflag) {
mcstatus(idx, delay, count);
} else if (cflag) {
mcosusage(idx, once, delay, count);
} else {
mcstatistics(idx, once, delay, count);
}
return 0;
}
static int
devopen(int idx)
{
int fd;
char fn[128];
snprintf(fn, 128, "/dev/mcos%d", idx);
fd = open(fn, O_RDONLY);
return fd;
}
static void
statistics_header(char *unit)
{
printf("------- memory (%s) ------- ------- tsc ------ --- thread ---\n",
unit);
printf(" total current max system user current max\n");
}
/*
* Device should be open in each ioctl time. Otherwise, this command grabs
* the device, and cannot be rebooted by others.
*/
static int
mygetrusage(int idx, struct mckernel_rusage *rbp)
{
int fd, rc;
struct mcctrl_ioctl_getrusage_desc rusage;
if ((fd = devopen(idx)) < 0) {
return -1;
}
rusage.rusage = rbp;
rusage.size_rusage = sizeof(struct mckernel_rusage);
memset(rbp, 0, sizeof(struct mckernel_rusage));
if ((rc = ioctl(fd, IHK_OS_GETRUSAGE, &rusage)) < 0) {
perror("ioctl"); exit(-1);
}
close(fd);
return 0;
}
static void
mcstatistics(int idx, int once, int delay, int count)
{
int i, scale;
char *unit;
unsigned char show = 0;
if (mygetrusage(idx, &rbuf) < 0) {
printf("Device has not been created.\n");
exit(-1);
}
if (rbuf.memory_max_usage < MiB100) {
scale = MiB; unit = "MB";
} else {
scale = GiB; unit = "GB";
}
statistics_header(unit);
for (;;) {
printf("%9.3f%9.3f%9.3f %9ld%9ld %7d %3d\n",
CONV_UNIT(rbuf.memory_max_usage),
CONV_UNIT(rbuf.memory_kmem_usage),
CONV_UNIT(rbuf.memory_kmem_max_usage),
rbuf.cpuacct_stat_system, rbuf.cpuacct_stat_user,
rbuf.num_threads, rbuf.max_num_threads);
if (count > 0 && --count == 0) break;
sleep(delay);
if (mygetrusage(idx, &rbuf) < 0) {
printf("Device is now invisible.\n");
break;
}
if (!once) {
if (UPDATE_COUNTER(show) == 0) {
statistics_header(unit);
}
}
}
/*
?? /1000000
rusage->cpuacct_stat_system = st / 10000000;
rusage->cpuacct_stat_user = ut / 10000000;
rusage->cpuacct_usage = ut;
printf("cpuacct_usage = %x\n", rbuf.cpuacct_usage);
*/
for (i = 0; i < rbuf.max_num_threads; i++) {
printf("cpuacct_usage_percpu[%d] = %ld\n", i, rbuf.cpuacct_usage_percpu[i]);
}
}
/* ihk_os_status enum is defined in ihk/linux/include/ihk/status.h */
static char *charstat[] = {
"None", /*IHK_OS_STATUS_NOT_BOOTED*/
"Booting", /*IHK_OS_STATUS_BOOTING*/
"Booted", /*IHK_OS_STATUS_BOOTED, OS booted and acked */
"Ready", /*IHK_OS_STATUS_READY, OS is ready and fully functional */
"Freezing", /*IHK_OS_STATUS_FREEZING, OS is freezing */
"Frozen", /*IHK_OS_STATUS_FROZEN, OS is frozen */
"Shutdown", /* IHK_OS_STATUS_SHUTDOWN, OS is shutting down */
"Stopped", /* IHK_OS_STATUS_STOPPED, OS stopped successfully */
"Panic", /* IHK_OS_STATUS_FAILED, OS panics or failed to boot */
"Hangup", /* IHK_OS_STATUS_HUNGUP, OS is hungup */
};
static void
mcstatus(int idx, int delay, int count)
{
int fd, rc;
for(;;) {
if ((fd = devopen(idx)) < 0) {
printf("Devide is not created\n");
} else {
rc = ioctl(fd, IHK_OS_STATUS, 0);
close(fd);
printf("McKernel status: ");
if (rc >= IHK_OS_STATUS_NOT_BOOTED && rc <= IHK_OS_STATUS_HUNGUP) {
printf("%s\n", charstat[rc]);
} else {
printf("ioctl error(IHK_OS_STATUS)\n");
}
}
if (count > 0 && --count == 0) break;
sleep(delay);
}
}
/* status is not contiguous numbers */
static char *
monstatus(int status)
{
switch (status) {
case IHK_OS_MONITOR_NOT_BOOT: return "boot";
case IHK_OS_MONITOR_IDLE: return "idle";
case IHK_OS_MONITOR_USER: return "user mode";
case IHK_OS_MONITOR_KERNEL: return "kernel mode";
case IHK_OS_MONITOR_KERNEL_HEAVY: return "kernel mode";
case IHK_OS_MONITOR_KERNEL_OFFLOAD: return "offload";
case IHK_OS_MONITOR_KERNEL_FREEZING:return "freezing";
case IHK_OS_MONITOR_KERNEL_FROZEN: return "frozen";
case IHK_OS_MONITOR_KERNEL_THAW: return "thaw";
case IHK_OS_MONITOR_PANIC: return "panic";
}
return "";
}
static void
osusage_header()
{
printf("--cpu-- --status-- --count--\n");
}
static void
mcosusage(int idx, int once, int delay, int count)
{
int fd, i, rc;
int ncpus;
unsigned char show = 0;
struct ihk_os_cpu_monitor mon[MAX_CPUS];
if (mygetrusage(idx, &rbuf) < 0) {
printf("Device has not been created.\n");
}
ncpus = rbuf.max_num_threads;
osusage_header();
for(;;) {
if ((fd = devopen(idx)) < 0) {
printf("Devide is not created\n");
} else {
rc = ioctl(fd, IHK_OS_GET_CPU_USAGE, &mon);
close(fd);
if (rc != 0) {
printf("ioctl error(IHK_OS_GET_CPU_USAGE)\n");
break;
}
for (i = 0; i < ncpus; i++) {
printf("%6d: %10s %9ld\n",
i, monstatus(mon[i].status), mon[i].counter);
}
}
if (count > 0 && --count == 0) break;
sleep(delay);
if (!once) {
if (UPDATE_COUNTER(show) == 0) {
osusage_header();
}
}
}
}