/* * mcstat -- reports McKernel statistis * mcstat [-h] * mcstat [-n] [delay [ count]] * mcstat [-s] * mcstat [-c] */ #include #include #include #include #include #include #include #include #include #include #include // mcctrl_ioctl_getrusage_desc is defined here #undef IHK_MAX_NUM_NUMA_NODES #include // 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(); } } } }