Hi Javi,
On 13 July 2016 at 15:07, Javi Merino <javi.merino(a)arm.com> wrote:
> The runtime event emulates the execution of a load for a specific amount
> of time irrespective of the compute capacity of the CPU it is run on or
> the frequency.
Thanks for adding this kind of event. It was on the TODO list
> ---
> doc/tutorial.txt | 5 +++++
> src/rt-app.c | 20 ++++++++++++++++++++
> src/rt-app_parse_config.c | 3 +++
> src/rt-app_types.h | 1 +
> 4 files changed, 29 insertions(+)
>
> diff --git a/doc/tutorial.txt b/doc/tutorial.txt
> index 6dc9a44..100a2df 100644
> --- a/doc/tutorial.txt
> +++ b/doc/tutorial.txt
> @@ -217,6 +217,11 @@ number of loop thanks to the ns per loop value (see calibration). This way of
> working enables to emulate a load with a duration that will vary with the
> frequency or the compute capacity of the CPU.
>
> +* runtime : Integer. The duration is define in usec. Similar to the
> +run event, it emulates the execution of a load. Unlike run, runtime
> +runs for a specific amount of time irrespective of the compute
> +capacity of the CPU or the frequency.
> +
> * sleep : Integer. Emulate the sleep of a task. The duration is defined in
> usec.
>
> diff --git a/src/rt-app.c b/src/rt-app.c
> index 679d39a..5283ac7 100644
> --- a/src/rt-app.c
> +++ b/src/rt-app.c
> @@ -274,6 +274,26 @@ static int run_event(event_data_t *event, int dry_run,
> *duration += timespec_to_usec(&t_end);
> }
> break;
> + case rtapp_runtime:
> + {
> + struct timespec t_start, t_end;
> + int64_t diff_ns;
> +
> + log_debug("runtime %d ", event->duration);
> + clock_gettime(CLOCK_MONOTONIC, &t_start);
> +
> + do {
> + /* Do work for 32usec */
I'm curious to know why you choose the value 32usec ?
This value seems to be a bit long for me. 10usec should be enough
> + *perf += loadwait(32);
> +
> + clock_gettime(CLOCK_MONOTONIC, &t_end);
> + diff_ns = timespec_sub_to_ns(&t_end, &t_start);
> + } while ((diff_ns / 1000) < event->duration);
> +
> + t_end = timespec_sub(&t_end, &t_start);
> + *duration += timespec_to_usec(&t_end);
> + }
> + break;
> case rtapp_timer:
> {
> struct timespec t_period, t_now;
> diff --git a/src/rt-app_parse_config.c b/src/rt-app_parse_config.c
> index 99b0e5e..c59b562 100644
> --- a/src/rt-app_parse_config.c
> +++ b/src/rt-app_parse_config.c
> @@ -348,6 +348,8 @@ parse_thread_event_data(char *name, struct json_object *obj,
>
> if (!strncmp(name, "sleep", strlen("sleep")))
> data->type = rtapp_sleep;
> + else if (!strncmp(name, "runtime", strlen("runtime")))
> + data->type = rtapp_runtime;
> else
> data->type = rtapp_run;
>
> @@ -558,6 +560,7 @@ static char *events[] = {
> "broad",
> "sync",
> "sleep",
> + "runtime",
Please move it after "run" to keep the same order as in run_event function
> "run",
> "timer",
> "suspend",
> diff --git a/src/rt-app_types.h b/src/rt-app_types.h
> index 2ce9c9d..57fb80d 100644
> --- a/src/rt-app_types.h
> +++ b/src/rt-app_types.h
> @@ -67,6 +67,7 @@ typedef enum resource_t
> rtapp_resume,
> rtapp_mem,
> rtapp_iorun,
> + rtapp_runtime,
> } resource_t;
>
> struct _rtapp_mutex {
> --
> 1.9.1
>
Hi Javi,
+Adding sched-tools list
Vincent
On 13 July 2016 at 15:07, Javi Merino <javi.merino(a)arm.com> wrote:
> Sometimes we need a create load that can run in any CPU of the
> system for a given period of time, regardless of their compute
> capacity. Add a runtime event to be able to generate such a load.
>
> Javi Merino (2):
> rt-parse: avoid repetition in obj_is_event()
> rt-app: add a runtime event
>
> doc/tutorial.txt | 5 +++++
> src/rt-app.c | 20 +++++++++++++++++
> src/rt-app_parse_config.c | 57 ++++++++++++++++++++++++-----------------------
> src/rt-app_types.h | 1 +
> 4 files changed, 55 insertions(+), 28 deletions(-)
>
> --
> 1.9.1
>
Add a BUILD file with instructions on how to cross-compile for
arm and arm64. Also update the README file to inform users where
they can submit feedback and patches to and fix trivial spelling
errors.
Signed-off-by: Lisa Nguyen <lisa.nguyen(a)linaro.org>
---
BUILD | 23 +++++++++++++++++++++++
README | 37 ++++++++++++++++++++++++++++++++++---
2 files changed, 57 insertions(+), 3 deletions(-)
create mode 100644 BUILD
diff --git a/BUILD b/BUILD
new file mode 100644
index 0000000..ca7c2ac
--- /dev/null
+++ b/BUILD
@@ -0,0 +1,23 @@
+To build idlestat natively, run 'make' from the top-level directory.
+
+Cross Compiling for ARM
+=======================
+These are instructions to cross compile for ARM and ARM64 on an Ubuntu system running x86_64.
+
+Requirements
+------------
+Depending on the target platform, you will need to download either the gnueabi or gnueabihf toolchain.
+
+For arm, run 'sudo apt-get install gcc-arm-linux-gnueabi' or 'sudo apt-get install gcc-arm-linux-gnueabihf'. You can also download these toolchains from Linaro at http://releases.linaro.org/components/toolchain/binaries/latest-5/arm-linux… or http://releases.linaro.org/components/toolchain/binaries/latest-5/arm-linux….
+
+For arm64, go to http://releases.linaro.org/components/toolchain/binaries/latest-5/aarch64-l… to download the latest aarch64 toolchain from Linaro. Then untar the toolchain tarball. Add the aarch64 toolchain directory path to the PATH environment variable by running 'export PATH=$PATH:<toolchain dir/bin>' (e.g. export PATH=$PATH:/home/<user>/gcc-linaro-5.3-2016.02-x86_64_aarch64-linux-gnu/bin).
+
+Steps
+------
+To build for arm, run "make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-" from the top-level directory.
+
+To build for arm64, run "make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-" from the top-level directory.
+
+Usage
+------
+Please refer to the README file or the idlestat manpage for details on how to use idlestat.
diff --git a/README b/README
index b519d1e..3203ba4 100644
--- a/README
+++ b/README
@@ -51,6 +51,37 @@ sudo ./idlestat --trace -f /tmp/mytrace -t 10 -- /bin/sleep 10
sudo ./idlestat --trace -f /tmp/myoutput -t 10 -- cyclictest -t 4 -i 2000 -q -D 5
Selective trace output
-sudo ./idlestate --import -f /tmp/mytrace -w
-sudo ./idlestate --import -f /tmp/mytrace -c -p
-sudo ./idlestate --import -f /tmp/mytrace -p -w
\ No newline at end of file
+sudo ./idlestat --import -f /tmp/mytrace -w
+sudo ./idlestat --import -f /tmp/mytrace -c -p
+sudo ./idlestat --import -f /tmp/mytrace -p -w
+
+Bugs
+----
+
+If you believe that you have encountered a bug, please file a bug report on
+Linaro Bugzilla at https://bugs.linaro.org. You may be prompted to register
+for a new account first.
+
+Once you log in, click on
+"New" --> "Power Management" --> "Idlestat" as the component. Then fill
+in the form.
+
+Helpful tips for filing a bug report:
+ 1. Provide logs, be verbose as possible
+ 2. Outline steps to reproduce the bug
+ 3. Describe the environment you are running idlestat on (e.g. Android,
+ OpenEmbedded, Ubuntu, etc.)
+ 4. What hardware you're using
+
+Contribution
+------------
+
+If you wish to submit patches to improve idlestat, please send them to
+the Linaro sched-tools mailing list at sched-tools(a)lists.linaro.org with
+"PATCH IDLESTAT" as the subject prefix.
+
+Feedback
+--------
+
+Please submit questions and comments to the Linaro sched-tools mailing list at
+sched-tools(a)lists.linaro.org with "idlestat" as part of the subject.
--
2.1.4
During my time working with the rt-app cpufreq efficiency test I came across a
few rough edges. Patches 1-4 address those.
Patch 5 essentially rewrites the test.sh script. Prior to this patch test.sh
takes a single governor and workload specification (duty cycle). It runs the
workload with this governor as well as the perf and power governors then
calculates efficiency. If we want to profile multiple governors, using this
script would result in running the workload under the perf and power governors
multiple times. You could run dvfs.sh script directly in which case the
efficiency must be manually calculated.
Patch 5 adds support to test.sh to accept a test specification file with the -f
parameter. A test specification file specifies the CPU to run the tests on, the
governors to test (excluding the perf and power governors), and the workloads
to test. It looks like this:
1
ondemand interactive schedutil
1 100 100
10 1000 10
1 10 1000
The workloads are specified as:
<busy time @fmax in ms> <period length in ms> <# of loops>
The results are output in a text-formatted table suitable for email.
CPU frequency residency is also tracked as part of patch 5. At the end of the
testing the residencies for each test for a given governor are printed in a
table. This depends on cpufreq stats being enabled on the platform.
The test.sh script continues to accept arguments as it did previously, i.e. it
will accept a single governor and workload on the command line.
Steve Muckle (5):
rt-app: fix cpufreq test loops
rt-app: change default sched class for dvfs test to SCHED_OTHER
rt-app: tidy up cpufreq efficiency README
rt-app: save and restore governor in dvfs.sh cpufreq efficency test
rt-app: rework cpufreq efficiency script
doc/examples/cpufreq_governor_efficiency/README | 85 ++++---
doc/examples/cpufreq_governor_efficiency/dvfs.json | 4 +-
doc/examples/cpufreq_governor_efficiency/dvfs.sh | 13 +-
doc/examples/cpufreq_governor_efficiency/test.sh | 246 ++++++++++++++-------
4 files changed, 238 insertions(+), 110 deletions(-)
--
2.7.3
In current code the CPU's idle state cpufreq_pstates::idle is initialized
to '-1'; and until parse first "cpu_idle" event for the CPU then set CPU's
idle state to '0' or '1' corresponding to active or idle. This will cause
error for P-state's statistics: from the beginning to first "cpu_idle"
event, during this period the CPU's idle state is '-1' so function
cpu_change_pstate() will always think it's first update and finally abandon
previous time.
This will introduce very big error if the CPU is always running and never
run into idle state. So this patch is to fix this issue by initialize CPU's
corresponding C-state and P-state:
- Firstly gather every CPU's starting frequency and time stamp;
- Then gather CPU's idle state according to first cpu_idle log:
If the CPU first cpu_idle state is '-1', that means from the beginning
the CPU is stayed on idle state;
If the CPU first cpu_idle state is other value, means the CPU is active.
- With these info, finally initialize every CPU's C-state and P-state
before analyse trace logs.
Here should note one thing is: when CPU is idle at beginning, we don't know
exact idle state, so just assume CPU is in idle state 0; but this will not
impact too much for statistics, due usually idlestat will wakeup all CPUs
at the beginning. So it will introduce very small deviation.
Signed-off-by: Leo Yan <leo.yan(a)linaro.org>
---
tracefile_idlestat.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 123 insertions(+)
diff --git a/tracefile_idlestat.c b/tracefile_idlestat.c
index 3430693..d0cd366 100644
--- a/tracefile_idlestat.c
+++ b/tracefile_idlestat.c
@@ -152,6 +152,127 @@ int load_text_data_line(char *buffer, struct cpuidle_datas *datas, char *format,
return get_wakeup_irq(datas, buffer);
}
+
+/**
+ * init_cpu_idle_state - Init CPU's idle state according to first cpu_idle log.
+ * For a specific cpu_idle event, its state is '-1' then that means from the
+ * beginning the CPU is stayed on idle state; Otherwise means the CPU is active.
+ * So initilize per-CPU idle flag to get more accurate time.
+ *
+ * @datas: structure for P-state and C-state's statistics
+ * @f: the file handle of the idlestat trace file
+ */
+void init_cpu_idle_state(struct cpuidle_datas *datas, FILE *f)
+{
+ char buffer[BUFSIZE];
+ int state, cpu;
+ double time;
+ struct cpufreq_pstates *ps;
+
+ unsigned long *cpu_start_idle;
+ int *cpu_start_freq;
+ double cpu_start_time;
+
+ fseek(f, 0, SEEK_SET);
+
+ cpu_start_freq = malloc(sizeof(int) * datas->nrcpus);
+ for (cpu = 0; cpu < datas->nrcpus; cpu++)
+ cpu_start_freq[cpu] = 0xdeadbeef;
+
+ /*
+ * Find the start time stamp and the CPU's frequency at beginning;
+ * So we can use these info to add dummy info.
+ */
+ while (fgets(buffer, BUFSIZE, f)) {
+
+ if (strstr(buffer, "cpu_frequency")) {
+ if (sscanf(buffer, TRACE_FORMAT, &time, &state, &cpu)
+ != 3) {
+ fprintf(stderr, "warning: Unrecognized cpuidle "
+ "record. The result of analysis might "
+ "be wrong.\n");
+ return;
+ }
+ } else
+ continue;
+
+ if (cpu_start_freq[cpu] != 0xdeadbeef)
+ continue;
+
+ if (cpu == 0)
+ cpu_start_time = time;
+
+ cpu_start_freq[cpu] = state;
+
+ break;
+ }
+
+ /* After traverse file, reset offset */
+ fseek(f, 0, SEEK_SET);
+
+ /*
+ * Find the CPU's idle state at beginning
+ */
+ cpu_start_idle = malloc(sizeof(long) * datas->nrcpus);
+ for (cpu = 0; cpu < datas->nrcpus; cpu++)
+ cpu_start_idle[cpu] = 0xdeadbeef;
+
+ while (fgets(buffer, BUFSIZE, f)) {
+
+ if (strstr(buffer, "cpu_idle")) {
+ if (sscanf(buffer, TRACE_FORMAT, &time, &state, &cpu)
+ != 3) {
+ fprintf(stderr, "warning: Unrecognized cpuidle "
+ "record. The result of analysis might "
+ "be wrong.\n");
+ return;
+ }
+ } else
+ continue;
+
+ /* CPU's state has been initialized, skip it */
+ if (cpu_start_idle[cpu] != 0xdeadbeef)
+ continue;
+
+ /*
+ * The CPU's first cpu_idle is '-1', means CPU is staying in
+ * idle state and exit from idle until first cpu_idle event.
+ * Otherwise, means the CPU is active at beginning.
+ */
+ if (state == -1)
+ cpu_start_idle[cpu] = 0;
+ else
+ cpu_start_idle[cpu] = 4294967295;
+ }
+
+ /* After traverse file, reset offset */
+ fseek(f, 0, SEEK_SET);
+
+ /* Initialize every CPU's cstate and pstate */
+ for (cpu = 0; cpu < datas->nrcpus; cpu++) {
+
+ ps = &(datas->pstates[cpu]);
+
+ if (cpu_start_idle[cpu] == 0) {
+ /*
+ * CPU is idle at beginning, init cstate;
+ *
+ * here don't know exact idle state, so just assume CPU
+ * is in idle state 0; but this will not impace too much
+ * for statistics, due usually idlestat will wakeup all
+ * CPUs at the beginning.
+ */
+ ps->idle = 1;
+ store_data(cpu_start_time, 0, cpu, datas);
+ } else {
+ /* CPU is busy at beginning, init pstate */
+ ps->idle = 0;
+ cpu_change_pstate(datas, cpu, cpu_start_freq[cpu],
+ cpu_start_time);
+ }
+ }
+}
+
void load_text_data_lines(FILE *f, char *buffer, struct cpuidle_datas *datas)
{
double begin = 0, end = 0;
@@ -159,6 +280,8 @@ void load_text_data_lines(FILE *f, char *buffer, struct cpuidle_datas *datas)
setup_topo_states(datas);
+ init_cpu_idle_state(datas, f);
+
do {
if (load_text_data_line(buffer, datas, TRACE_FORMAT,
&begin, &end, &start) != -1) {
--
1.9.1
In current code the CPU's idle state cpufreq_pstates::idle is initialized
to '-1'; and until parse first "cpu_idle" event for the CPU then set CPU's
idle state to '0' or '1' corresponding to active or idle. This will cause
error for P-state's statistics: from the beginning to first "cpu_idle"
event, during this period the CPU's idle state is '-1' so function
cpu_change_pstate() will always think it's first update and finally abandon
previous time.
This will introduce very big error if the CPU is always running and never
run into idle state. So this patch is to fix this issue by initialize CPU's
corresponding C-state and P-state:
- Firstly gather every CPU's starting frequency and time stamp;
- Then gather CPU's idle state according to first cpu_idle log:
If the CPU first cpu_idle state is '-1', that means from the beginning
the CPU is stayed on idle state;
If the CPU first cpu_idle state is other value, means the CPU is active.
- With these info, finally initialize every CPU's C-state and P-state
before analyse trace logs.
Here should note one thing is: when CPU is idle at beginning, we don't know
exact idle state, so just assume CPU is in idle state 0; but this will not
impact too much for statistics, due usually idlestat will wakeup all CPUs
at the beginning. So it will introduce very small deviation.
Signed-off-by: Leo Yan <leo.yan(a)linaro.org>
---
tracefile_idlestat.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 152 insertions(+)
diff --git a/tracefile_idlestat.c b/tracefile_idlestat.c
index 3430693..2674478 100644
--- a/tracefile_idlestat.c
+++ b/tracefile_idlestat.c
@@ -152,6 +152,153 @@ int load_text_data_line(char *buffer, struct cpuidle_datas *datas, char *format,
return get_wakeup_irq(datas, buffer);
}
+
+/**
+ * init_cpu_idle_state - Init CPU's idle state according to first cpu_idle log.
+ * For a specific cpu_idle event, its state is '-1' then that means from the
+ * beginning the CPU is stayed on idle state; Otherwise means the CPU is active.
+ * So initilize per-CPU idle flag to get more accurate time.
+ *
+ * @datas: structure for P-state and C-state's statistics
+ * @f: the file handle of the idlestat trace file
+ */
+int init_cpu_idle_state(struct cpuidle_datas *datas, FILE *f)
+{
+ char buffer[BUFSIZE];
+ int state, cpu;
+ double time;
+ struct cpufreq_pstates *ps;
+
+ unsigned long *cpu_start_idle;
+ int *cpu_start_freq;
+ double cpu_start_time;
+
+ int ret;
+
+ ret = fseek(f, 0, SEEK_SET);
+ if (ret < 0) {
+ fprintf(stderr, "failed to set the start file position\n");
+ return ret;
+ }
+
+ cpu_start_freq = malloc(sizeof(int) * datas->nrcpus);
+ if (!cpu_start_freq) {
+ fprintf(stderr, "failed to alloc for start frequency states\n");
+ return -1;
+ }
+
+ for (cpu = 0; cpu < datas->nrcpus; cpu++)
+ cpu_start_freq[cpu] = 0xdeadbeef;
+
+ /*
+ * Find the start time stamp and the CPU's frequency at beginning;
+ * So we can use these info to add dummy info.
+ */
+ while (fgets(buffer, BUFSIZE, f)) {
+
+ if (strstr(buffer, "cpu_frequency")) {
+ if (sscanf(buffer, TRACE_FORMAT, &time, &state, &cpu)
+ != 3) {
+ fprintf(stderr, "warning: Unrecognized cpuidle "
+ "record. The result of analysis might "
+ "be wrong.\n");
+ return -1;
+ }
+ } else
+ continue;
+
+ if (cpu_start_freq[cpu] != 0xdeadbeef)
+ continue;
+
+ if (cpu == 0)
+ cpu_start_time = time;
+
+ cpu_start_freq[cpu] = state;
+
+ break;
+ }
+
+ /* After traverse file, reset offset */
+ ret = fseek(f, 0, SEEK_SET);
+ if (ret < 0) {
+ fprintf(stderr, "failed to set the start file position\n");
+ return ret;
+ }
+
+ /*
+ * Find the CPU's idle state at beginning
+ */
+ cpu_start_idle = malloc(sizeof(long) * datas->nrcpus);
+ if (!cpu_start_idle) {
+ fprintf(stderr, "failed to alloc for start idle states\n");
+ return -1;
+ }
+
+ for (cpu = 0; cpu < datas->nrcpus; cpu++)
+ cpu_start_idle[cpu] = 0xdeadbeef;
+
+ while (fgets(buffer, BUFSIZE, f)) {
+
+ if (strstr(buffer, "cpu_idle")) {
+ if (sscanf(buffer, TRACE_FORMAT, &time, &state, &cpu)
+ != 3) {
+ fprintf(stderr, "warning: Unrecognized cpuidle "
+ "record. The result of analysis might "
+ "be wrong.\n");
+ return -1;
+ }
+ } else
+ continue;
+
+ /* CPU's state has been initialized, skip it */
+ if (cpu_start_idle[cpu] != 0xdeadbeef)
+ continue;
+
+ /*
+ * The CPU's first cpu_idle is '-1', means CPU is staying in
+ * idle state and exit from idle until first cpu_idle event.
+ * Otherwise, means the CPU is active at beginning.
+ */
+ if (state == -1)
+ cpu_start_idle[cpu] = 0;
+ else
+ cpu_start_idle[cpu] = 4294967295;
+ }
+
+ /* After traverse file, reset offset */
+ ret = fseek(f, 0, SEEK_SET);
+ if (ret < 0) {
+ fprintf(stderr, "failed to set the start file position\n");
+ return ret;
+ }
+
+ /* Initialize every CPU's cstate and pstate */
+ for (cpu = 0; cpu < datas->nrcpus; cpu++) {
+
+ ps = &(datas->pstates[cpu]);
+
+ if (cpu_start_idle[cpu] == 0) {
+ /*
+ * CPU is idle at beginning, init cstate;
+ *
+ * here don't know exact idle state, so just assume CPU
+ * is in idle state 0; but this will not impace too much
+ * for statistics, due usually idlestat will wakeup all
+ * CPUs at the beginning.
+ */
+ ps->idle = 1;
+ store_data(cpu_start_time, 0, cpu, datas);
+ } else {
+ /* CPU is busy at beginning, init pstate */
+ ps->idle = 0;
+ cpu_change_pstate(datas, cpu, cpu_start_freq[cpu],
+ cpu_start_time);
+ }
+ }
+
+ return 0;
+}
+
void load_text_data_lines(FILE *f, char *buffer, struct cpuidle_datas *datas)
{
double begin = 0, end = 0;
@@ -159,6 +306,11 @@ void load_text_data_lines(FILE *f, char *buffer, struct cpuidle_datas *datas)
setup_topo_states(datas);
+ if (init_cpu_idle_state(datas, f) < 0) {
+ fprintf(stderr, "failed to initlized cpu states\n");
+ exit(-1);
+ }
+
do {
if (load_text_data_line(buffer, datas, TRACE_FORMAT,
&begin, &end, &start) != -1) {
--
1.9.1
+ adding sched-tools mailing list
On 17 May 2016 at 03:02, Leo Yan <leo.yan(a)linaro.org> wrote:
> In current code the CPU's idle state cpufreq_pstates::idle is initialized
> to '-1'; and until parse first "cpu_idle" event for the CPU then set CPU's
> idle state to '0' or '1' corresponding to active or idle. This will cause
> error for P-state's statistics: from the beginning to first "cpu_idle"
> event, during this period the CPU's idle state is '-1' so function
> cpu_change_pstate() will always think it's first update and finally abandon
> previous time.
>
> This will introduce very big error if the CPU is always running and never
> run into idle state. So this patch is to fix this issue by initialize CPU's
> idle state before parse P-state and C-state's time. Initialize CPU's idle
> state according to first cpu_idle log:
> - If the CPU first cpu_idle state is '-1', that means from the beginning
> the CPU is stayed on idle state;
> - If the CPU first cpu_idle state is other value, means the CPU is active.
>
> Signed-off-by: Leo Yan <leo.yan(a)linaro.org>
> ---
> tracefile_idlestat.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 51 insertions(+)
>
> diff --git a/tracefile_idlestat.c b/tracefile_idlestat.c
> index 3430693..fb0b3d8 100644
> --- a/tracefile_idlestat.c
> +++ b/tracefile_idlestat.c
> @@ -152,6 +152,55 @@ int load_text_data_line(char *buffer, struct cpuidle_datas *datas, char *format,
> return get_wakeup_irq(datas, buffer);
> }
>
> +/**
> + * init_cpu_idle_state - Init CPU's idle state according to first cpu_idle log.
> + * For a specific cpu_idle event, its state is '-1' then that means from the
> + * beginning the CPU is stayed on idle state; Otherwise means the CPU is active.
> + * So initilize per-CPU idle flag to get more accurate time.
> + *
> + * @datas: structure for P-state and C-state's statistics
> + * @f: the file handle of the idlestat trace file
> + */
> +void init_cpu_idle_state(struct cpuidle_datas *datas, FILE *f)
> +{
> + struct cpufreq_pstates *ps;
> + unsigned int state, freq, cpu;
> + double time;
> + char buffer[BUFSIZE];
> +
> + do {
> + if (strstr(buffer, "cpu_idle")) {
> + if (sscanf(buffer, TRACE_FORMAT, &time, &state, &cpu)
> + != 3) {
> + fprintf(stderr, "warning: Unrecognized cpuidle "
> + "record. The result of analysis might "
> + "be wrong.\n");
> + return -1;
> + }
> + }
> +
> + ps = &(datas->pstates[cpu]);
> +
> + /* CPU's state has been initialized, skip it */
> + if (ps->idle != -1)
> + continue;
> +
> + /*
> + * The CPU's first cpu_idle is '-1', means CPU is staying in
> + * idle state and exit from idle until first cpu_idle event.
> + * Otherwise, means the CPU is active at beginning.
> + */
> + if (state == -1)
> + ps->idle = 1;
> + else
> + ps->idle = 0;
> +
> + } while (fgets(buffer, BUFSIZE, f));
> +
> + /* After traverse file, reset offset */
> + fseek(f, 0, SEEK_SET);
> +}
> +
> void load_text_data_lines(FILE *f, char *buffer, struct cpuidle_datas *datas)
> {
> double begin = 0, end = 0;
> @@ -159,6 +208,8 @@ void load_text_data_lines(FILE *f, char *buffer, struct cpuidle_datas *datas)
>
> setup_topo_states(datas);
>
> + init_cpu_idle_state(datas, f);
> +
> do {
> if (load_text_data_line(buffer, datas, TRACE_FORMAT,
> &begin, &end, &start) != -1) {
> --
> 1.9.1
>
Hi Juri,
This series mainly intends to introduce calibration mechanism and simplify the
grammar used in JSON files. [4, 5, 6] of this series are exceptions but also
put in this series since the following grammar simplification patches are
highly dependent on those features and removal of command line interface
done in [4, 5, 6].
This series are also found in:
ssh://git@git.linaro.org/people/picheng.chen/rt-app.git calibration_grammar_series
Vincent Guittot (9):
make load frequency independent
fix calibration issue on mt8173
describe resource names in plain string
add run and sleep resource types
add phase feature
remove support of command line interface
simplify grammar of JSON files
make global object optional
make resource object optional
README.in | 79 +-------
src/rt-app.c | 451 +++++++++++++++++++++++++-----------------
src/rt-app_args.c | 328 +------------------------------
src/rt-app_args.h | 3 -
src/rt-app_parse_config.c | 492 +++++++++++++++++++++++++++-------------------
src/rt-app_types.h | 63 +++---
src/rt-app_utils.c | 64 +++++-
src/rt-app_utils.h | 3 +
8 files changed, 666 insertions(+), 817 deletions(-)
--
1.9.1