# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1231413683 0
# Node ID e9cd8e7c3b4402b10d2d35e13cbf2d90a52a0bfa
# Parent 95d77829216fdad92f16690d7899508bec38ee0e
xenpm tool enhancements
Two enhancements 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@xxxxxxxxx>Signed-off-by: Ke Yu
<ke.yu@xxxxxxxxx>
---
tools/misc/xenpm.c | 893 ++++++++++++++++++++++++++++++++---------------------
1 files changed, 552 insertions(+), 341 deletions(-)
diff -r 95d77829216f -r e9cd8e7c3b44 tools/misc/xenpm.c
--- a/tools/misc/xenpm.c Thu Jan 08 11:19:38 2009 +0000
+++ b/tools/misc/xenpm.c Thu Jan 08 11:21:23 2009 +0000
@@ -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 */
-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)
-{
- 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;
- }
+}
+
+static void print_cxstat(int cpuid, struct xc_cx_stat *cxstat)
+{
+ 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);
}
-
- 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 };
-
- 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;
- }
- }
- }
- else
- ret = show_cx_cpuid(xc_fd, cpuid);
-
- return ret;
-}
-
-/* show cpu frequency information on CPU cpuid */
-static int show_px_cpuid(int xc_fd, int cpuid)
-{
- 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);
+ struct xc_cx_stat cxstatinfo;
+
+ ret = get_cxstat_by_cpuid(xc_fd, cpuid, &cxstatinfo);
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;
- }
+ 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 cpus */
+ int i;
+ for ( i = 0; i < max_cpu_nr; i++ )
+ if ( show_cxstat_by_cpuid(xc_fd, i) == -ENODEV )
+ break;
+ }
+ else
+ show_cxstat_by_cpuid(xc_fd, cpuid);
+}
+
+static void print_pxstat(int cpuid, struct xc_px_stat *pxstat)
+{
+ 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);
}
-
- 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 };
-
- if ( cpuid < 0 )
- {
- ret = xc_physinfo(xc_fd, &physinfo);
- if ( ret )
+ 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 )
+ {
+ /* 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]);
+ }
}
}
- }
- else
- ret = show_px_cpuid(xc_fd, cpuid);
-
- return ret;
+ 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
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)
-{
- int ret = 0;
- xc_physinfo_t physinfo = { 0 };
-
- if ( cpuid < 0 )
- {
- ret = xc_physinfo(xc_fd, &physinfo);
- if ( ret )
+void cpufreq_para_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 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
+ show_cpufreq_para_by_cpuid(xc_fd, cpuid);
+}
+
+void scaling_max_freq_func(int argc, char *argv[])
+{
+ 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 )
+ {
+ 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);
+ }
+ else
+ {
+ if ( xc_set_cpufreq_para(xc_fd, cpuid, SCALING_MAX_FREQ, freq) )
+ fprintf(stderr, "failed to set scaling max freq\n");
+ }
+}
+
+void scaling_min_freq_func(int argc, char *argv[])
+{
+ 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 )
+ {
+ 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);
+ }
+ else
+ {
+ if ( xc_set_cpufreq_para(xc_fd, cpuid, SCALING_MIN_FREQ, freq) )
+ fprintf(stderr, "failed to set scaling min freq\n");
+ }
+}
+
+void scaling_speed_func(int argc, char *argv[])
+{
+ 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 )
+ {
+ 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);
+ }
+ else
+ {
+ if ( xc_set_cpufreq_para(xc_fd, cpuid, SCALING_SETSPEED, speed) )
+ fprintf(stderr, "failed to set scaling speed\n");
+ }
+}
+
+void scaling_sampling_rate_func(int argc, char *argv[])
+{
+ 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 )
+ {
+ 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);
+ }
+ else
+ {
+ if ( xc_set_cpufreq_para(xc_fd, cpuid, SAMPLING_RATE, rate) )
+ fprintf(stderr, "failed to set scaling sampling rate\n");
+ }
+}
+
+void scaling_up_threshold_func(int argc, char *argv[])
+{
+ 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 )
+ {
+ 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);
+ }
+ else
+ {
+ if ( xc_set_cpufreq_para(xc_fd, cpuid, UP_THRESHOLD, threshold) )
+ fprintf(stderr, "failed to set up scaling threshold\n");
+ }
+}
+
+void scaling_governor_func(int argc, char *argv[])
+{
+ 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 )
{
- fprintf(stderr, "failed to get the processor information\n");
+ free(name);
+ goto out;
}
- else
- {
- int i;
- for ( i = 0; i < physinfo.nr_cpus; i++ )
- {
- if ( (ret = show_cpufreq_para_cpuid(xc_fd, i)) == -ENODEV )
- break;
- }
- }
- }
- else
- ret = show_cpufreq_para_cpuid(xc_fd, cpuid);
-
- return ret;
-}
-
-int scaling_max_freq_func(int xc_fd, int cpuid, uint32_t value)
-{
- int ret = 0;
-
- if ( cpuid < 0 )
- {
- show_help();
- return -EINVAL;
- }
-
- ret = xc_set_cpufreq_para(xc_fd, cpuid, SCALING_MAX_FREQ, value);
- if ( ret )
- {
- fprintf(stderr, "[CPU%d] failed to set scaling max freq\n", cpuid);
- }
-
- return ret;
-}
-
-int scaling_min_freq_func(int xc_fd, int cpuid, uint32_t value)
-{
- int ret;
-
- if ( cpuid < 0 )
- {
- show_help();
- return -EINVAL;
- }
-
- ret = xc_set_cpufreq_para(xc_fd, cpuid, SCALING_MIN_FREQ, value);
- if ( ret )
- {
- fprintf(stderr, "[CPU%d] failed to set scaling min freq\n", cpuid);
- }
-
- return ret;
-}
-
-int scaling_speed_func(int xc_fd, int cpuid, uint32_t value)
-{
- int ret;
-
- if ( cpuid < 0 )
- {
- show_help();
- return -EINVAL;
- }
-
- ret = xc_set_cpufreq_para(xc_fd, cpuid, SCALING_SETSPEED, value);
- if ( ret )
- {
- fprintf(stderr, "[CPU%d] failed to set scaling speed\n", cpuid);
- }
-
- return ret;
-}
-
-int scaling_sampling_rate_func(int xc_fd, int cpuid, uint32_t value)
-{
- int ret;
-
- if ( cpuid < 0 )
- {
- show_help();
- return -EINVAL;
- }
-
- ret = xc_set_cpufreq_para(xc_fd, cpuid, SAMPLING_RATE, value);
- if ( ret )
- {
- fprintf(stderr, "[CPU%d] failed to set scaling sampling rate\n",
cpuid);
- }
-
- return ret;
-}
-
-int scaling_up_threshold_func(int xc_fd, int cpuid, uint32_t value)
-{
- int ret;
-
- if ( cpuid < 0 )
- {
- show_help();
- return -EINVAL;
- }
-
- ret = xc_set_cpufreq_para(xc_fd, cpuid, UP_THRESHOLD, value);
- if ( ret )
- {
- fprintf(stderr, "[CPU%d] failed to set scaling threshold\n", cpuid);
- }
-
- return ret;
-}
-
-int scaling_governor_func(int xc_fd, int cpuid, char *name)
-{
- int ret = 0;
-
- if ( cpuid < 0 )
- {
- show_help();
- return -EINVAL;
- }
-
- ret = xc_set_cpufreq_gov(xc_fd, cpuid, name);
- if ( ret )
- {
- fprintf(stderr, "failed to set cpufreq governor to %s\n", name);
- }
-
- return ret;
+ }
+ else if ( argc > 0 )
+ {
+ name = strdup(argv[0]);
+ if ( name == NULL )
+ goto out;
+ }
+ else
+ goto out;
+
+ if ( cpuid < 0 )
+ {
+ 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");
+ }
+
+ 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-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|