xenpm tool enhancements Two enahncements are made in this patch: 1. Make cpuid in command line optional: if user does not provide cpuid, xenpm will operate on all the CPUs. this will easy the xenpm usage. e.g. to set the cpufreq governor, user usually want to set the governor on all CPUs. user can accomplish this easily with this enhancement. 2. Add another option "xenpm start" to calculate the Cx/Px state residency percentage during specified period. when user issue "xenpm start", xenpm will start to record the Cx/Px state residency. when user issue CTRL-C, xenpm will stop and show the Cx/Px state residency and percentage of this period. this is helpful to measure the xenpm effect for speficied workload. Signed-off-by: Guanqun Lu <guanqun.lu@intel.com> Signed-off-by: Ke Yu <ke.yu@intel.com> diff -r b9721b2766c1 tools/misc/xenpm.c --- a/tools/misc/xenpm.c +++ b/tools/misc/xenpm.c @@ -21,83 +21,55 @@ #include <stdio.h> #include <stdlib.h> +#include <unistd.h> #include <string.h> #include <getopt.h> #include <errno.h> +#include <signal.h> #include <xenctrl.h> #include <inttypes.h> #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 <cpuid> <HZ>: set max cpu frequency <HZ> on CPU <cpuid>.\n" - " xenpm set-scaling-minfreq <cpuid> <HZ>: set min cpu frequency <HZ> on CPU <cpuid>.\n" - " xenpm set-scaling-governor <cpuid> <name>: set scaling governor on CPU <cpuid>.\n" - " xenpm set-scaling-speed <cpuid> <num>: set scaling speed on CPU <cpuid>.\n" - " xenpm set-sampling-rate <cpuid> <num>: set sampling rate on CPU <cpuid>.\n" - " xenpm set-up-threshold <cpuid> <num>: set up threshold on CPU <cpuid>.\n"); + "xen power management control tool\n\n" + "usage: xenpm <command> [args]\n\n" + "xenpm command list:\n\n" + " get-cpuidle-states [cpuid] list cpu idle info of CPU <cpuid> or all\n" + " get-cpufreq-states [cpuid] list cpu freq info of CPU <cpuid> or all\n" + " get-cpufreq-para [cpuid] list cpu freq parameter of CPU <cpuid> or all\n" + " set-scaling-maxfreq [cpuid] <HZ> set max cpu frequency <HZ> on CPU <cpuid>\n" + " or all CPUs\n" + " set-scaling-minfreq [cpuid] <HZ> set min cpu frequency <HZ> on CPU <cpuid>\n" + " or all CPUs\n" + " set-scaling-speed [cpuid] <num> set scaling speed on CPU <cpuid> or all\n" + " it is used in userspace governor.\n" + " set-scaling-governor [cpuid] <gov> set scaling governor on CPU <cpuid> or all\n" + " as userspace/performance/powersave/ondemand\n" + " set-sampling-rate [cpuid] <num> set sampling rate on CPU <cpuid> or all\n" + " it is used in ondemand governor.\n" + " set-up-threshold [cpuid] <num> set up threshold on CPU <cpuid> 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 */ +void help_func(int argc, char *argv[]) +{ + show_help(); } -/* wrapper function */ -int help_func(int xc_fd, int cpuid, uint32_t value) +static void print_cxstat(int cpuid, struct xc_cx_stat *cxstat) { - show_help(); - return 0; -} - -/* show cpu idle information on CPU cpuid */ -static int show_cx_cpuid(int xc_fd, int cpuid) -{ - 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 printf(" residency [%020"PRIu64" ms]\n", cxstat->residencies[i]/1000000UL); } + printf("\n"); +} - free(cxstat->triggers); - free(cxstat->residencies); +/* 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; - printf("\n"); + 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 printf(" residency [%020"PRIu64" ms]\n", pxstat->pt[i].residency/1000000UL); } + printf("\n"); +} - free(pxstat->trans_pt); - free(pxstat->pt); +/* 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; - printf("\n"); + 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 ) + /* 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 + show_pxstat_by_cpuid(xc_fd, cpuid); +} + +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 ) { - fprintf(stderr, "failed to get the processor information\n"); - } - else - { - int i; - for ( i = 0; i < physinfo.nr_cpus; i++ ) + for ( j = 0; j < cxstat_end[i].nr; j++ ) { - if ( (ret = show_px_cpuid(xc_fd, i)) == -ENODEV ) - break; + 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"); } - else - ret = show_px_cpuid(xc_fd, cpuid); - return ret; + /* 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 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 } /* 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); + } + else + { + if ( xc_set_cpufreq_gov(xc_fd, cpuid, name) ) + fprintf(stderr, "failed to set governor name\n"); } - ret = xc_set_cpufreq_gov(xc_fd, cpuid, name); - if ( ret ) - { - fprintf(stderr, "failed to set cpufreq governor to %s\n", name); - } - - 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; } + ret = xc_physinfo(xc_fd, &physinfo); + if ( ret ) + { + 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; } _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel