#include #include #include #include #include #include #include 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);