diff --git a/tools/misc/xenpm.c b/tools/misc/xenpm.c index c3b19584bc..55523c6965 100644 --- a/tools/misc/xenpm.c +++ b/tools/misc/xenpm.c @@ -21,83 +21,55 @@ #include #include +#include #include #include #include +#include #include #include #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) +static int xc_fd; +static int max_cpu_nr; + /* help message */ void show_help(void) { fprintf(stderr, - "Usage:\n" - " xenpm get-cpuidle-states [cpuid]: list cpu idle information on CPU cpuid or all CPUs.\n" - " xenpm get-cpufreq-states [cpuid]: list cpu frequency information on CPU cpuid or all CPUs.\n" - " xenpm get-cpufreq-para [cpuid]: list cpu frequency information on CPU cpuid or all CPUs.\n" - " xenpm set-scaling-maxfreq : set max cpu frequency on CPU .\n" - " xenpm set-scaling-minfreq : set min cpu frequency on CPU .\n" - " xenpm set-scaling-governor : set scaling governor on CPU .\n" - " xenpm set-scaling-speed : set scaling speed on CPU .\n" - " xenpm set-sampling-rate : set sampling rate on CPU .\n" - " xenpm set-up-threshold : set up threshold on CPU .\n"); + "xen power management control tool\n\n" + "usage: xenpm [args]\n\n" + "xenpm command list:\n\n" + " get-cpuidle-states [cpuid] list cpu idle info of CPU or all\n" + " get-cpufreq-states [cpuid] list cpu freq info of CPU or all\n" + " get-cpufreq-para [cpuid] list cpu freq parameter of CPU or all\n" + " set-scaling-maxfreq [cpuid] set max cpu frequency on CPU \n" + " or all CPUs\n" + " set-scaling-minfreq [cpuid] set min cpu frequency on CPU \n" + " or all CPUs\n" + " set-scaling-speed [cpuid] set scaling speed on CPU or all\n" + " it is used in userspace governor.\n" + " set-scaling-governor [cpuid] set scaling governor on CPU or all\n" + " as userspace/performance/powersave/ondemand\n" + " set-sampling-rate [cpuid] set sampling rate on CPU or all\n" + " it is used in ondemand governor.\n" + " set-up-threshold [cpuid] set up threshold on CPU or all\n" + " it is used in ondemand governor.\n" + " start start collect Cx/Px statistics,\n" + " output after CTRL-C or SIGINT.\n" + ); } - /* wrapper function */ -int help_func(int xc_fd, int cpuid, uint32_t value) +void help_func(int argc, char *argv[]) { show_help(); - return 0; } -/* show cpu idle information on CPU cpuid */ -static int show_cx_cpuid(int xc_fd, int cpuid) +static void print_cxstat(int cpuid, struct xc_cx_stat *cxstat) { - int i, ret = 0; - int max_cx_num = 0; - struct xc_cx_stat cxstatinfo, *cxstat = &cxstatinfo; - - ret = xc_pm_get_max_cx(xc_fd, cpuid, &max_cx_num); - if ( ret ) - { - if ( errno == ENODEV ) - { - fprintf(stderr, "Xen cpuidle is not enabled!\n"); - return -ENODEV; - } - else - { - fprintf(stderr, "[CPU%d] failed to get max C-state\n", cpuid); - return -EINVAL; - } - } - - cxstat->triggers = malloc(max_cx_num * sizeof(uint64_t)); - if ( !cxstat->triggers ) - { - fprintf(stderr, "[CPU%d] failed to malloc for C-states triggers\n", cpuid); - return -ENOMEM; - } - cxstat->residencies = malloc(max_cx_num * sizeof(uint64_t)); - if ( !cxstat->residencies ) - { - fprintf(stderr, "[CPU%d] failed to malloc for C-states residencies\n", cpuid); - free(cxstat->triggers); - return -ENOMEM; - } - - ret = xc_pm_get_cxstat(xc_fd, cpuid, cxstat); - if( ret ) - { - fprintf(stderr, "[CPU%d] failed to get C-states statistics " - "information\n", cpuid); - free(cxstat->triggers); - free(cxstat->residencies); - return -EINVAL; - } + int i; printf("cpu id : %d\n", cpuid); printf("total C-states : %d\n", cxstat->nr); @@ -110,88 +82,87 @@ static int show_cx_cpuid(int xc_fd, int cpuid) printf(" residency [%020"PRIu64" ms]\n", cxstat->residencies[i]/1000000UL); } - - free(cxstat->triggers); - free(cxstat->residencies); - printf("\n"); +} + +/* show cpu idle information on CPU cpuid */ +static int get_cxstat_by_cpuid(int xc_fd, int cpuid, struct xc_cx_stat *cxstat) +{ + int ret = 0; + int max_cx_num = 0; + + ret = xc_pm_get_max_cx(xc_fd, cpuid, &max_cx_num); + if ( ret ) + return errno; + + if ( !cxstat ) + return -EINVAL; + + cxstat->triggers = malloc(max_cx_num * sizeof(uint64_t)); + if ( !cxstat->triggers ) + return -ENOMEM; + cxstat->residencies = malloc(max_cx_num * sizeof(uint64_t)); + if ( !cxstat->residencies ) + { + free(cxstat->triggers); + return -ENOMEM; + } + + ret = xc_pm_get_cxstat(xc_fd, cpuid, cxstat); + if( ret ) + { + int temp = errno; + free(cxstat->triggers); + free(cxstat->residencies); + cxstat->triggers = NULL; + cxstat->residencies = NULL; + return temp; + } + return 0; } -int cxstates_func(int xc_fd, int cpuid, uint32_t value) +static int show_cxstat_by_cpuid(int xc_fd, int cpuid) { int ret = 0; - xc_physinfo_t physinfo = { 0 }; + struct xc_cx_stat cxstatinfo; + + ret = get_cxstat_by_cpuid(xc_fd, cpuid, &cxstatinfo); + if ( ret ) + return ret; + + print_cxstat(cpuid, &cxstatinfo); + + free(cxstatinfo.triggers); + free(cxstatinfo.residencies); + return 0; +} + +void cxstat_func(int argc, char *argv[]) +{ + int cpuid = -1; + + if ( argc > 0 && sscanf(argv[0], "%d", &cpuid) != 1 ) + cpuid = -1; + + if ( cpuid >= max_cpu_nr ) + cpuid = -1; if ( cpuid < 0 ) { - /* show cxstates on all cpu */ - ret = xc_physinfo(xc_fd, &physinfo); - if ( ret ) - { - fprintf(stderr, "failed to get the processor information\n"); - } - else - { - int i; - for ( i = 0; i < physinfo.nr_cpus; i++ ) - { - if ( (ret = show_cx_cpuid(xc_fd, i)) == -ENODEV ) - break; - } - } + /* show cxstates on all cpus */ + int i; + for ( i = 0; i < max_cpu_nr; i++ ) + if ( show_cxstat_by_cpuid(xc_fd, i) == -ENODEV ) + break; } else - ret = show_cx_cpuid(xc_fd, cpuid); - - return ret; + show_cxstat_by_cpuid(xc_fd, cpuid); } -/* show cpu frequency information on CPU cpuid */ -static int show_px_cpuid(int xc_fd, int cpuid) +static void print_pxstat(int cpuid, struct xc_px_stat *pxstat) { - int i, ret = 0; - int max_px_num = 0; - struct xc_px_stat pxstatinfo, *pxstat = &pxstatinfo; - - ret = xc_pm_get_max_px(xc_fd, cpuid, &max_px_num); - if ( ret ) - { - if ( errno == ENODEV ) - { - printf("Xen cpufreq is not enabled!\n"); - return -ENODEV; - } - else - { - fprintf(stderr, "[CPU%d] failed to get max P-state\n", cpuid); - return -EINVAL; - } - } - - pxstat->trans_pt = malloc(max_px_num * max_px_num * - sizeof(uint64_t)); - if ( !pxstat->trans_pt ) - { - fprintf(stderr, "[CPU%d] failed to malloc for P-states transition table\n", cpuid); - return -ENOMEM; - } - pxstat->pt = malloc(max_px_num * sizeof(struct xc_px_val)); - if ( !pxstat->pt ) - { - fprintf(stderr, "[CPU%d] failed to malloc for P-states table\n", cpuid); - free(pxstat->trans_pt); - return -ENOMEM; - } - - ret = xc_pm_get_pxstat(xc_fd, cpuid, pxstat); - if( ret ) - { - fprintf(stderr, "[CPU%d] failed to get P-states statistics information\n", cpuid); - free(pxstat->trans_pt); - free(pxstat->pt); - return -ENOMEM; - } + int i; printf("cpu id : %d\n", cpuid); printf("total P-states : %d\n", pxstat->total); @@ -211,40 +182,233 @@ static int show_px_cpuid(int xc_fd, int cpuid) printf(" residency [%020"PRIu64" ms]\n", pxstat->pt[i].residency/1000000UL); } - - free(pxstat->trans_pt); - free(pxstat->pt); - printf("\n"); +} + +/* show cpu frequency information on CPU cpuid */ +static int get_pxstat_by_cpuid(int xc_fd, int cpuid, struct xc_px_stat *pxstat) +{ + int ret = 0; + int max_px_num = 0; + + ret = xc_pm_get_max_px(xc_fd, cpuid, &max_px_num); + if ( ret ) + return errno; + + if ( !pxstat) + return -EINVAL; + + pxstat->trans_pt = malloc(max_px_num * max_px_num * + sizeof(uint64_t)); + if ( !pxstat->trans_pt ) + return -ENOMEM; + pxstat->pt = malloc(max_px_num * sizeof(struct xc_px_val)); + if ( !pxstat->pt ) + { + free(pxstat->trans_pt); + return -ENOMEM; + } + + ret = xc_pm_get_pxstat(xc_fd, cpuid, pxstat); + if( ret ) + { + int temp = errno; + free(pxstat->trans_pt); + free(pxstat->pt); + pxstat->trans_pt = NULL; + pxstat->pt = NULL; + return temp; + } + return 0; } -int pxstates_func(int xc_fd, int cpuid, uint32_t value) +static int show_pxstat_by_cpuid(int xc_fd, int cpuid) { int ret = 0; - xc_physinfo_t physinfo = { 0 }; + struct xc_px_stat pxstatinfo; + + ret = get_pxstat_by_cpuid(xc_fd, cpuid, &pxstatinfo); + if ( ret ) + return ret; + + print_pxstat(cpuid, &pxstatinfo); + + free(pxstatinfo.trans_pt); + free(pxstatinfo.pt); + return 0; +} + +void pxstat_func(int argc, char *argv[]) +{ + int cpuid = -1; + + if ( argc > 0 && sscanf(argv[0], "%d", &cpuid) != 1 ) + cpuid = -1; + + if ( cpuid >= max_cpu_nr ) + cpuid = -1; if ( cpuid < 0 ) { - ret = xc_physinfo(xc_fd, &physinfo); - if ( ret ) - { - fprintf(stderr, "failed to get the processor information\n"); - } - else - { - int i; - for ( i = 0; i < physinfo.nr_cpus; i++ ) - { - if ( (ret = show_px_cpuid(xc_fd, i)) == -ENODEV ) - break; - } - } + /* show pxstates on all cpus */ + int i; + for ( i = 0; i < max_cpu_nr; i++ ) + if ( show_pxstat_by_cpuid(xc_fd, i) == -ENODEV ) + break; } else - ret = show_px_cpuid(xc_fd, cpuid); + show_pxstat_by_cpuid(xc_fd, cpuid); +} - return ret; +static uint64_t usec_start, usec_end; +static struct xc_cx_stat *cxstat, *cxstat_start, *cxstat_end; +static struct xc_px_stat *pxstat, *pxstat_start, *pxstat_end; +static uint64_t *sum, *sum_cx, *sum_px; + +static void signal_int_handler(int signo) +{ + int i, j; + struct timeval tv; + int cx_cap = 0, px_cap = 0; + + if ( gettimeofday(&tv, NULL) == -1 ) + { + fprintf(stderr, "failed to get timeofday\n"); + return ; + } + usec_end = tv.tv_sec * 1000000UL + tv.tv_usec; + + if ( get_cxstat_by_cpuid(xc_fd, 0, NULL) != -ENODEV ) + { + cx_cap = 1; + for ( i = 0; i < max_cpu_nr; i++ ) + if ( !get_cxstat_by_cpuid(xc_fd, i, &cxstat_end[i]) ) + for ( j = 0; j < cxstat_end[i].nr; j++ ) + sum_cx[i] += cxstat_end[i].residencies[j] - + cxstat_start[i].residencies[j]; + } + + if ( get_pxstat_by_cpuid(xc_fd, 0, NULL) != -ENODEV ) + { + px_cap = 1; + for ( i = 0; i < max_cpu_nr; i++ ) + if ( !get_pxstat_by_cpuid(xc_fd, i , &pxstat_end[i]) ) + for ( j = 0; j < pxstat_end[i].total; j++ ) + sum_px[i] += pxstat_end[i].pt[j].residency - + pxstat_start[i].pt[j].residency; + } + + printf("Elapsed time (ms): %"PRIu64"\n", (usec_end - usec_start) / 1000UL); + for ( i = 0; i < max_cpu_nr; i++ ) + { + uint64_t temp; + printf("CPU%d:\n\tresidency\tpercentage\n", i); + if ( cx_cap ) + { + for ( j = 0; j < cxstat_end[i].nr; j++ ) + { + if ( sum_cx[i] > 0 ) + { + temp = cxstat_end[i].residencies[j] - + cxstat_start[i].residencies[j]; + printf(" C%d\t%"PRIu64" ms\t%.2f%%\n", j, + temp / 1000000UL, 100UL * temp / (double)sum_cx[i]); + } + } + } + if ( px_cap ) + { + for ( j = 0; j < pxstat_end[i].total; j++ ) + { + if ( sum_px[i] > 0 ) + { + temp = pxstat_end[i].pt[j].residency - + pxstat_start[i].pt[j].residency; + printf(" P%d\t%"PRIu64" ms\t%.2f%%\n", j, + temp / 1000000UL, 100UL * temp / (double)sum_px[i]); + } + } + } + printf("\n"); + } + + /* some clean up and then exits */ + for ( i = 0; i < 2 * max_cpu_nr; i++ ) + { + free(cxstat[i].triggers); + free(cxstat[i].residencies); + free(pxstat[i].trans_pt); + free(pxstat[i].pt); + } + free(cxstat); + free(pxstat); + free(sum); + xc_interface_close(xc_fd); + exit(0); +} + +void start_gather_func(int argc, char *argv[]) +{ + int i; + struct timeval tv; + + if ( gettimeofday(&tv, NULL) == -1 ) + { + fprintf(stderr, "failed to get timeofday\n"); + return ; + } + usec_start = tv.tv_sec * 1000000UL + tv.tv_usec; + + sum = malloc(sizeof(uint64_t) * 2 * max_cpu_nr); + if ( sum == NULL ) + return ; + cxstat = malloc(sizeof(struct xc_cx_stat) * 2 * max_cpu_nr); + if ( cxstat == NULL ) + { + free(sum); + return ; + } + pxstat = malloc(sizeof(struct xc_px_stat) * 2 * max_cpu_nr); + if ( pxstat == NULL ) + { + free(sum); + free(cxstat); + return ; + } + memset(sum, 0, sizeof(uint64_t) * 2 * max_cpu_nr); + memset(cxstat, 0, sizeof(struct xc_cx_stat) * 2 * max_cpu_nr); + memset(pxstat, 0, sizeof(struct xc_px_stat) * 2 * max_cpu_nr); + sum_cx = sum; + sum_px = sum + max_cpu_nr; + cxstat_start = cxstat; + cxstat_end = cxstat + max_cpu_nr; + pxstat_start = pxstat; + pxstat_end = pxstat + max_cpu_nr; + + if ( get_cxstat_by_cpuid(xc_fd, 0, NULL) == -ENODEV && + get_pxstat_by_cpuid(xc_fd, 0, NULL) == -ENODEV ) + { + fprintf(stderr, "Xen cpu idle and frequency is disabled!\n"); + return ; + } + + for ( i = 0; i < max_cpu_nr; i++ ) + { + get_cxstat_by_cpuid(xc_fd, i, &cxstat_start[i]); + get_pxstat_by_cpuid(xc_fd, i, &pxstat_start[i]); + } + + if (signal(SIGINT, signal_int_handler) == SIG_ERR) + { + fprintf(stderr, "failed to set signal int handler\n"); + free(sum); + free(pxstat); + free(cxstat); + return ; + } + + pause(); } /* print out parameters about cpu frequency */ @@ -294,7 +458,8 @@ static void print_cpufreq_para(int cpuid, struct xc_get_cpufreq_para *p_cpufreq) printf("scaling_avail_freq :"); for ( i = 0; i < p_cpufreq->freq_num; i++ ) - if ( p_cpufreq->scaling_available_frequencies[i] == p_cpufreq->scaling_cur_freq ) + if ( p_cpufreq->scaling_available_frequencies[i] == + p_cpufreq->scaling_cur_freq ) printf(" *%d", p_cpufreq->scaling_available_frequencies[i]); else printf(" %d", p_cpufreq->scaling_available_frequencies[i]); @@ -308,7 +473,7 @@ static void print_cpufreq_para(int cpuid, struct xc_get_cpufreq_para *p_cpufreq) } /* show cpu frequency parameters information on CPU cpuid */ -static int show_cpufreq_para_cpuid(int xc_fd, int cpuid) +static int show_cpufreq_para_by_cpuid(int xc_fd, int cpuid) { int ret = 0; struct xc_get_cpufreq_para cpufreq_para, *p_cpufreq = &cpufreq_para; @@ -381,159 +546,221 @@ out: return ret; } -int cpufreq_para_func(int xc_fd, int cpuid, uint32_t value) +void cpufreq_para_func(int argc, char *argv[]) { - int ret = 0; - xc_physinfo_t physinfo = { 0 }; + int cpuid = -1; + + if ( argc > 0 && sscanf(argv[0], "%d", &cpuid) != 1 ) + cpuid = -1; + + if ( cpuid >= max_cpu_nr ) + cpuid = -1; if ( cpuid < 0 ) { - ret = xc_physinfo(xc_fd, &physinfo); - if ( ret ) - { - fprintf(stderr, "failed to get the processor information\n"); - } - else - { - int i; - for ( i = 0; i < physinfo.nr_cpus; i++ ) - { - if ( (ret = show_cpufreq_para_cpuid(xc_fd, i)) == -ENODEV ) - break; - } - } + /* show cpu freqency information on all cpus */ + int i; + for ( i = 0; i < max_cpu_nr; i++ ) + if ( show_cpufreq_para_by_cpuid(xc_fd, i) == -ENODEV ) + break; } else - ret = show_cpufreq_para_cpuid(xc_fd, cpuid); - - return ret; + show_cpufreq_para_by_cpuid(xc_fd, cpuid); } -int scaling_max_freq_func(int xc_fd, int cpuid, uint32_t value) +void scaling_max_freq_func(int argc, char *argv[]) { - int ret = 0; + int cpuid = -1, freq = -1; + + if ( (argc >= 2 && (sscanf(argv[1], "%d", &freq) != 1 || + sscanf(argv[0], "%d", &cpuid) != 1)) || + (argc == 1 && sscanf(argv[0], "%d", &freq) != 1 ) || + argc == 0 ) + { + fprintf(stderr, "failed to set scaling max freq\n"); + return ; + } if ( cpuid < 0 ) { - show_help(); - return -EINVAL; + int i; + for ( i = 0; i < max_cpu_nr; i++ ) + if ( xc_set_cpufreq_para(xc_fd, i, SCALING_MAX_FREQ, freq) ) + fprintf(stderr, "[CPU%d] failed to set scaling max freq\n", i); } - - ret = xc_set_cpufreq_para(xc_fd, cpuid, SCALING_MAX_FREQ, value); - if ( ret ) + else { - fprintf(stderr, "[CPU%d] failed to set scaling max freq\n", cpuid); + if ( xc_set_cpufreq_para(xc_fd, cpuid, SCALING_MAX_FREQ, freq) ) + fprintf(stderr, "failed to set scaling max freq\n"); } - - return ret; } -int scaling_min_freq_func(int xc_fd, int cpuid, uint32_t value) +void scaling_min_freq_func(int argc, char *argv[]) { - int ret; + int cpuid = -1, freq = -1; + + if ( (argc >= 2 && (sscanf(argv[1], "%d", &freq) != 1 || + sscanf(argv[0], "%d", &cpuid) != 1) ) || + (argc == 1 && sscanf(argv[0], "%d", &freq) != 1 ) || + argc == 0 ) + { + fprintf(stderr, "failed to set scaling min freq\n"); + return ; + } if ( cpuid < 0 ) { - show_help(); - return -EINVAL; + int i; + for ( i = 0; i < max_cpu_nr; i++ ) + if ( xc_set_cpufreq_para(xc_fd, i, SCALING_MIN_FREQ, freq) ) + fprintf(stderr, "[CPU%d] failed to set scaling min freq\n", i); } - - ret = xc_set_cpufreq_para(xc_fd, cpuid, SCALING_MIN_FREQ, value); - if ( ret ) + else { - fprintf(stderr, "[CPU%d] failed to set scaling min freq\n", cpuid); + if ( xc_set_cpufreq_para(xc_fd, cpuid, SCALING_MIN_FREQ, freq) ) + fprintf(stderr, "failed to set scaling min freq\n"); } - - return ret; } -int scaling_speed_func(int xc_fd, int cpuid, uint32_t value) +void scaling_speed_func(int argc, char *argv[]) { - int ret; + int cpuid = -1, speed = -1; + + if ( (argc >= 2 && (sscanf(argv[1], "%d", &speed) != 1 || + sscanf(argv[0], "%d", &cpuid) != 1) ) || + (argc == 1 && sscanf(argv[0], "%d", &speed) != 1 ) || + argc == 0 ) + { + fprintf(stderr, "failed to set scaling speed\n"); + return ; + } if ( cpuid < 0 ) { - show_help(); - return -EINVAL; + int i; + for ( i = 0; i < max_cpu_nr; i++ ) + if ( xc_set_cpufreq_para(xc_fd, i, SCALING_SETSPEED, speed) ) + fprintf(stderr, "[CPU%d] failed to set scaling speed\n", i); } - - ret = xc_set_cpufreq_para(xc_fd, cpuid, SCALING_SETSPEED, value); - if ( ret ) + else { - fprintf(stderr, "[CPU%d] failed to set scaling speed\n", cpuid); + if ( xc_set_cpufreq_para(xc_fd, cpuid, SCALING_SETSPEED, speed) ) + fprintf(stderr, "failed to set scaling speed\n"); } - - return ret; } -int scaling_sampling_rate_func(int xc_fd, int cpuid, uint32_t value) +void scaling_sampling_rate_func(int argc, char *argv[]) { - int ret; + int cpuid = -1, rate = -1; + + if ( (argc >= 2 && (sscanf(argv[1], "%d", &rate) != 1 || + sscanf(argv[0], "%d", &cpuid) != 1) ) || + (argc == 1 && sscanf(argv[0], "%d", &rate) != 1 ) || + argc == 0 ) + { + fprintf(stderr, "failed to set scaling sampling rate\n"); + return ; + } if ( cpuid < 0 ) { - show_help(); - return -EINVAL; + int i; + for ( i = 0; i < max_cpu_nr; i++ ) + if ( xc_set_cpufreq_para(xc_fd, i, SAMPLING_RATE, rate) ) + fprintf(stderr, + "[CPU%d] failed to set scaling sampling rate\n", i); } - - ret = xc_set_cpufreq_para(xc_fd, cpuid, SAMPLING_RATE, value); - if ( ret ) + else { - fprintf(stderr, "[CPU%d] failed to set scaling sampling rate\n", cpuid); + if ( xc_set_cpufreq_para(xc_fd, cpuid, SAMPLING_RATE, rate) ) + fprintf(stderr, "failed to set scaling sampling rate\n"); } - - return ret; } -int scaling_up_threshold_func(int xc_fd, int cpuid, uint32_t value) +void scaling_up_threshold_func(int argc, char *argv[]) { - int ret; + int cpuid = -1, threshold = -1; + + if ( (argc >= 2 && (sscanf(argv[1], "%d", &threshold) != 1 || + sscanf(argv[0], "%d", &cpuid) != 1) ) || + (argc == 1 && sscanf(argv[0], "%d", &threshold) != 1 ) || + argc == 0 ) + { + fprintf(stderr, "failed to set up scaling threshold\n"); + return ; + } if ( cpuid < 0 ) { - show_help(); - return -EINVAL; + int i; + for ( i = 0; i < max_cpu_nr; i++ ) + if ( xc_set_cpufreq_para(xc_fd, i, UP_THRESHOLD, threshold) ) + fprintf(stderr, + "[CPU%d] failed to set up scaling threshold\n", i); } - - ret = xc_set_cpufreq_para(xc_fd, cpuid, UP_THRESHOLD, value); - if ( ret ) + else { - fprintf(stderr, "[CPU%d] failed to set scaling threshold\n", cpuid); + if ( xc_set_cpufreq_para(xc_fd, cpuid, UP_THRESHOLD, threshold) ) + fprintf(stderr, "failed to set up scaling threshold\n"); } - - return ret; } -int scaling_governor_func(int xc_fd, int cpuid, char *name) +void scaling_governor_func(int argc, char *argv[]) { - int ret = 0; + int cpuid = -1; + char *name = NULL; + + if ( argc >= 2 ) + { + name = strdup(argv[1]); + if ( name == NULL ) + goto out; + if ( sscanf(argv[0], "%d", &cpuid) != 1 ) + { + free(name); + goto out; + } + } + else if ( argc > 0 ) + { + name = strdup(argv[0]); + if ( name == NULL ) + goto out; + } + else + goto out; if ( cpuid < 0 ) { - show_help(); - return -EINVAL; + int i; + for ( i = 0; i < max_cpu_nr; i++ ) + if ( xc_set_cpufreq_gov(xc_fd, i, name) ) + fprintf(stderr, "[CPU%d] failed to set governor name\n", i); } - - ret = xc_set_cpufreq_gov(xc_fd, cpuid, name); - if ( ret ) + else { - fprintf(stderr, "failed to set cpufreq governor to %s\n", name); + if ( xc_set_cpufreq_gov(xc_fd, cpuid, name) ) + fprintf(stderr, "failed to set governor name\n"); } - return ret; + free(name); + return ; +out: + fprintf(stderr, "failed to set governor name\n"); } struct { const char *name; - int (*function)(int xc_fd, int cpuid, uint32_t value); + void (*function)(int argc, char *argv[]); } main_options[] = { { "help", help_func }, - { "get-cpuidle-states", cxstates_func }, - { "get-cpufreq-states", pxstates_func }, + { "get-cpuidle-states", cxstat_func }, + { "get-cpufreq-states", pxstat_func }, + { "start", start_gather_func }, { "get-cpufreq-para", cpufreq_para_func }, { "set-scaling-maxfreq", scaling_max_freq_func }, { "set-scaling-minfreq", scaling_min_freq_func }, - { "set-scaling-governor", NULL }, + { "set-scaling-governor", scaling_governor_func }, { "set-scaling-speed", scaling_speed_func }, { "set-sampling-rate", scaling_sampling_rate_func }, { "set-up-threshold", scaling_up_threshold_func }, @@ -541,38 +768,37 @@ struct { int main(int argc, char *argv[]) { - int i, ret = -EINVAL; - int xc_fd; - int cpuid = -1; - uint32_t value = 0; + int i, ret = 0; + xc_physinfo_t physinfo = { 0 }; int nr_matches = 0; int matches_main_options[ARRAY_SIZE(main_options)]; if ( argc < 2 ) { show_help(); - return ret; - } - - if ( argc > 2 ) - { - if ( sscanf(argv[2], "%d", &cpuid) != 1 ) - cpuid = -1; + return 0; } xc_fd = xc_interface_open(); if ( xc_fd < 0 ) { fprintf(stderr, "failed to get the handler\n"); + return 0; } - for ( i = 0; i < ARRAY_SIZE(main_options); i++ ) + ret = xc_physinfo(xc_fd, &physinfo); + if ( ret ) { - if ( !strncmp(main_options[i].name, argv[1], strlen(argv[1])) ) - { - matches_main_options[nr_matches++] = i; - } + fprintf(stderr, "failed to get the processor information\n"); + xc_interface_close(xc_fd); + return 0; } + max_cpu_nr = physinfo.nr_cpus; + + /* calculate how many options match with user's input */ + for ( i = 0; i < ARRAY_SIZE(main_options); i++ ) + if ( !strncmp(main_options[i].name, argv[1], strlen(argv[1])) ) + matches_main_options[nr_matches++] = i; if ( nr_matches > 1 ) { @@ -582,27 +808,12 @@ int main(int argc, char *argv[]) fprintf(stderr, "\n"); } else if ( nr_matches == 1 ) - { - if ( !strcmp("set-scaling-governor", main_options[matches_main_options[0]].name) ) - { - char *name = strdup(argv[3]); - ret = scaling_governor_func(xc_fd, cpuid, name); - free(name); - } - else - { - if ( argc > 3 ) - { - if ( sscanf(argv[3], "%d", &value) != 1 ) - value = 0; - } - ret = main_options[matches_main_options[0]].function(xc_fd, cpuid, value); - } - } + /* dispatch to the corresponding function handler */ + main_options[matches_main_options[0]].function(argc - 2, argv + 2); else show_help(); xc_interface_close(xc_fd); - return ret; + return 0; }