[RFC-PATCH] Improve Menu Governor Prediction of interrupted C states.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

Any comments on the following?

I'm finding with high interrupt rates for some USB devices the menu governor guesses wrong enough that throughput drops.

With the below tweak tests with fixed data sizes which were taking 12s to complete drop back to 9s.  Also my standby idle doesn't change before and after activity with our with out the patch.

What it does is simply timestamp incoming irqs, then in the menu governor will use current & last irq time delta to refine its guess as to how long sleep will happen.

Regards,
Richard W.

Signed-off-by: Richard Woodruff <r-woodruff2@xxxxxx>

diff -purN img/2.6_kernel/arch/arm/kernel/irq.c 2.6_kernel/arch/arm/kernel/irq.c
--- img/2.6_kernel/arch/arm/kernel/irq.c        2008-04-03 22:43:09.000000000 -0500
+++ 2.6_kernel/arch/arm/kernel/irq.c    2008-07-14 15:09:48.000000000 -0500
@@ -122,6 +131,8 @@ asmlinkage void __exception asm_do_IRQ(u

        irq_enter();

+       kstat_irq_stamp();
+
        desc_handle_irq(irq, desc);

        /* AT91 specific workaround */
diff -purN img/2.6_kernel/drivers/cpuidle/governors/menu.c 2.6_kernel/drivers/cpuidle/governors/menu.c
--- img/2.6_kernel/drivers/cpuidle/governors/menu.c     2008-07-04 15:31:23.000000000 -0500
+++ 2.6_kernel/drivers/cpuidle/governors/menu.c 2008-07-14 15:22:55.000000000 -0500
@@ -7,6 +7,7 @@
  */

 #include <linux/kernel.h>
+#include <linux/kernel_stat.h>
 #include <linux/cpuidle.h>
 #include <linux/latency.h>
 #include <linux/time.h>
@@ -70,6 +71,7 @@ static void menu_reflect(struct cpuidle_
        unsigned int measured_us =
                cpuidle_get_last_residency(dev) + data->elapsed_us;
        struct cpuidle_state *target = &dev->states[last_idx];
+       const unsigned int cpu = smp_processor_id();

        /*
         * Ugh, this idle state doesn't support residency measurements, so we
@@ -92,6 +94,10 @@ static void menu_reflect(struct cpuidle_
                        data->elapsed_us = -1;
                data->predicted_us = max(measured_us, data->last_measured_us);
        }
+
+       /* Guess & factor in interrupt wake rate */
+       data->predicted_us = min((s64)data->predicted_us, ktime_to_us(
+               ktime_sub(kstat_cpu(cpu).irq_now, kstat_cpu(cpu).irq_last)));
 }

 /**
diff -purN img/2.6_kernel/include/linux/kernel_stat.h 2.6_kernel/include/linux/kernel_stat.h
--- img/2.6_kernel/include/linux/kernel_stat.h  2008-04-03 21:51:50.000000000 -0500
+++ 2.6_kernel/include/linux/kernel_stat.h      2008-07-14 13:11:09.000000000 -0500
@@ -7,6 +7,7 @@
 #include <linux/percpu.h>
 #include <linux/cpumask.h>
 #include <asm/cputime.h>
+#include <linux/hrtimer.h>

 /*
  * 'kernel_stat.h' contains the definitions needed for doing
@@ -29,6 +30,8 @@ struct cpu_usage_stat {
 struct kernel_stat {
        struct cpu_usage_stat   cpustat;
        unsigned int irqs[NR_IRQS];
+       ktime_t irq_now;
+       ktime_t irq_last;
 };

 DECLARE_PER_CPU(struct kernel_stat, kstat);
@@ -52,6 +55,16 @@ static inline int kstat_irqs(int irq)
        return sum;
 }

+/*
+ * Provide hook to try and understand interrupt rate on a processor
+ */
+static inline void kstat_irq_stamp(void)
+{
+       const unsigned int cpu = smp_processor_id();
+       kstat_cpu(cpu).irq_last = kstat_cpu(cpu).irq_now;
+       kstat_cpu(cpu).irq_now = ktime_get();
+}
+
 extern void account_user_time(struct task_struct *, cputime_t);
 extern void account_user_time_scaled(struct task_struct *, cputime_t);
 extern void account_system_time(struct task_struct *, int, cputime_t);

Attachment: menu_gov_irq_guess.diff
Description: menu_gov_irq_guess.diff

_______________________________________________
linux-pm mailing list
linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

[Index of Archives]     [Linux ACPI]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [CPU Freq]     [Kernel Newbies]     [Fedora Kernel]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux