On 02/01/2012 04:15 PM, Daniel Lezcano wrote:

Yes, but the problem is the same also. Did you try
by removing atomic_inc and set nrunnings to nrkthread ?

Unfortunately it's still here:

Unable to handle kernel paging request at virtual address 7f0a411c
pgd = 80004000
[7f0a411c] *pgd=bf163811, *pte=00000000, *ppte=00000000
Internal error: Oops: 80000007 [#1] PREEMPT SMP
Modules linked in: [last unloaded: testmod]
CPU: 0    Tainted: G           O  (3.3.0-rc2+ #2)
PC is at 0x7f0a411c
LR is at __schedule+0x684/0x6e4
pc : [<7f0a411c>]    lr : [<802c0bdc>]    psr: 600f0113
sp : bf3b5f78  ip : 00000000  fp : 00000000
r10: 00000000  r9 : 00000000  r8 : 7f0a4538
r7 : 00000002  r6 : 00000400  r5 : 0000003c  r4 : 00000001
r3 : 00000000  r2 : bf3b5eb0  r1 : bf219580  r0 : 00000001
Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment kernel
Control: 10c5387d  Table: bfbec04a  DAC: 00000015
Process test/124 (pid: 6772, stack limit = 0xbf3b42f8)
Stack: (0xbf3b5f78 to 0xbf3b6000)
5f60:                                                       7b11940d 0000003c
5f80: 000f4240 00000000 00000001 000b07b6 bf8c9e44 00000000 7f0a4000 00000013
5fa0: 00000000 80049260 00000000 00000000 00000000 00000000 00000000 00000000
5fc0: dead4ead ffffffff ffffffff 8048b2b8 00000000 00000000 8036a4d9 bf3b5fdc
5fe0: bf3b5fdc 271aee1c bf8c9e44 800491d4 8000eabc 8000eabc bfefc811 bfefcc11
Code: bad PC value

If someone wants to look at it, I'm attaching everything. The patch is almost 
nothing beyond
exporting irq_time_read() to modules.

Note it's quite rare - to reproduce it, I do

while true; do insmod testmod.ko usehrtime=1 && rmmod testmod.ko; sleep 1; done

and wait for a few minutes.

Dmitry
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/hardirq.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/ktime.h>

MODULE_LICENSE("GPL");

static int nrthreads = 128;
module_param(nrthreads, int, 0644);

static int loopcount = 1024;
module_param(loopcount, int, 0644);

static int usehrtime = 0;
module_param(usehrtime, int, 0644);

static int slack = 50000;
module_param(slack, int, 0644);

static int msecs = 1;
module_param(msecs, int, 0644);

static DEFINE_PER_CPU(u64, cpu_irq_time);
static DECLARE_COMPLETION(done);
static struct task_struct **threads;
static atomic_t nrunning;
static ktime_t start;

static void timeout_init_irq_time(void *unused)
{
        int cpu = smp_processor_id();

        per_cpu(cpu_irq_time, cpu) = irq_time_read(cpu);
}

static void timeout_show_irq_time(void *unused)
{
        int cpu = smp_processor_id();
        u64 irqtime = irq_time_read(cpu) - per_cpu(cpu_irq_time, cpu);

        printk("cpu%d spent %llu usecs in irqs\n",
               cpu, div64_u64(irqtime, NSEC_PER_USEC));
}

static int test(void *unused)
{
        int i;
        ktime_t expires = ktime_set(0, msecs * NSEC_PER_MSEC);

        for (i = 0; !kthread_should_stop() && i < loopcount; i++) {
                if (usehrtime) {
                        set_current_state(TASK_UNINTERRUPTIBLE);
                        schedule_hrtimeout_range(&expires, slack, 
HRTIMER_MODE_REL);
                }
                else
                        
schedule_timeout_uninterruptible(msecs_to_jiffies(msecs));
        }

        if (atomic_dec_and_test(&nrunning)) {
                on_each_cpu(timeout_show_irq_time, NULL, 1);
                printk("-- timeout test end, %lld msecs elapsed --\n",
                       ktime_to_ms(ktime_sub(ktime_get(), start)));
                complete(&done);
        }
        return 0;
}

static int __init testmod_init(void)
{
        int i;

        printk("-- %d-threads, %d-loops timeout test for %d-msecs timeouts, use 
%s",
               nrthreads, loopcount, msecs,
               (usehrtime ? "high-res timeout " : "jiffies timeout "));
        if (usehrtime)
                printk("with %u-nsecs slack --\n", slack);
        else
                printk("--\n");

        start = ktime_get();
        atomic_set(&nrunning, nrthreads);
        on_each_cpu(timeout_init_irq_time, NULL, 1);

        threads = kmalloc(nrthreads * sizeof(struct task_struct *), GFP_KERNEL);
        if (!threads)
                return -ENOMEM;

        for (i = 0; i < nrthreads; i++) {
                threads[i] = kthread_run(test, NULL, "test/%d", i);
                if (IS_ERR(threads[i])) {
                        int j, err = PTR_ERR(threads[i]);

                        for (j = 0; j < i; j++)
                                kthread_stop(threads[j]);
                        kfree(threads);
                        return err;
                }
        }
        return 0;
}

static void __exit testmod_exit(void)
{
        wait_for_completion(&done);
        kfree(threads);
}

module_init(testmod_init);
module_exit(testmod_exit);
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 5bed94e..4759676 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -805,17 +805,6 @@ config SCHED_MC
          making when dealing with multi-core CPU chips at a cost of slightly
          increased overhead in some places. If unsure say N here.
 
-config IRQ_TIME_ACCOUNTING
-       bool "Fine granularity task level IRQ time accounting"
-       default n
-       ---help---
-         Select this option to enable fine granularity task irq time
-         accounting. This is done by reading a timestamp on each
-         transitions between softirq and hardirq state, so there can be a
-         small performance impact.
-
-         If in doubt, say N here.
-
 source "kernel/Kconfig.preempt"
 
 config X86_UP_APIC
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index bb7f309..3d08f8d 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -137,6 +137,7 @@ static inline void account_system_vtime(struct task_struct 
*tsk)
 }
 #else
 extern void account_system_vtime(struct task_struct *tsk);
+extern u64 irq_time_read(int cpu);
 #endif
 
 #if defined(CONFIG_TINY_RCU) || defined(CONFIG_TINY_PREEMPT_RCU)
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index df00cb0..b033d78 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -762,7 +762,7 @@ static DEFINE_PER_CPU(u64, cpu_hardirq_time);
 static DEFINE_PER_CPU(u64, cpu_softirq_time);
 
 static DEFINE_PER_CPU(u64, irq_start_time);
-static int sched_clock_irqtime;
+static int sched_clock_irqtime = 1;
 
 void enable_sched_clock_irqtime(void)
 {
@@ -789,7 +789,7 @@ static inline void irq_time_write_end(void)
        __this_cpu_inc(irq_time_seq.sequence);
 }
 
-static inline u64 irq_time_read(int cpu)
+u64 __sched irq_time_read(int cpu)
 {
        u64 irq_time;
        unsigned seq;
@@ -811,12 +811,14 @@ static inline void irq_time_write_end(void)
 {
 }
 
-static inline u64 irq_time_read(int cpu)
+u64 __sched irq_time_read(int cpu)
 {
        return per_cpu(cpu_softirq_time, cpu) + per_cpu(cpu_hardirq_time, cpu);
 }
 #endif /* CONFIG_64BIT */
 
+EXPORT_SYMBOL(irq_time_read);
+
 /*
  * Called before incrementing preempt_count on {soft,}irq_enter
  * and before decrementing preempt_count on {soft,}irq_exit.
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 8745ac7..d6d7afc 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -299,6 +299,17 @@ config SCHEDSTATS
          application, you can say N to avoid the very slight overhead
          this adds.
 
+config IRQ_TIME_ACCOUNTING
+       bool "Fine granularity task level IRQ time accounting"
+       default n
+       ---help---
+         Select this option to enable fine granularity task irq time
+         accounting. This is done by reading a timestamp on each
+         transitions between softirq and hardirq state, so there can be a
+         small performance impact.
+
+         If in doubt, say N here.
+
 config TIMER_STATS
        bool "Collect kernel timers statistics"
        depends on DEBUG_KERNEL && PROC_FS
_______________________________________________
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev

Reply via email to