From f555d61e4d5b19a4b81c8a56e66cafaee0ede45e Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 18 Jan 2013 14:10:12 +0530 Subject: workqueue: Start timer from work Signed-off-by: Viresh Kumar --- workqueue.c | 49 ++++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/workqueue.c b/workqueue.c index b99d768..a92377b 100644 --- a/workqueue.c +++ b/workqueue.c @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -43,8 +44,6 @@ struct mywork { int cpu; } *_myworks; -unsigned int _myworks_index; - struct mytimer { struct timer_list _timer; unsigned int timer_count_left; @@ -66,13 +65,13 @@ static DEFINE_PER_CPU(struct workqueue_struct *, cpu_wq); static int total_works_per_timer = 1000, total_works_finished; -#define TIMER_DELAY 10 +#define TIMER_DELAY 5 static DEFINE_PER_CPU(struct mytimer, _cpu_mytimer); DECLARE_COMPLETION(wq_complete); void timer_fn(unsigned long data) { - int index, cpu = raw_smp_processor_id(); + int cpu = raw_smp_processor_id(); struct mytimer *_mytimer = (struct mytimer *)data; struct mytimer *cpu_mytimer = &per_cpu(_cpu_mytimer, cpu); struct workqueue_struct **wq = &per_cpu(cpu_wq, cpu); @@ -83,20 +82,9 @@ void timer_fn(unsigned long data) if (cpu != _mytimer->cpu) cpu_mytimer->timer_migration_count++; - spin_lock(&tlock); - index = _myworks_index++; - spin_unlock(&tlock); - - /* queue work and re-arm timer on current cpu */ - _myworks[index].cpu = cpu; - queue_work_on_any_cpu(*wq, &_myworks[index]._work); + /* queue work on any cpu */ + queue_work_on_any_cpu(*wq, &_myworks[_mytimer->cpu]._work); ++(*work_queued_count); - - if (--(_mytimer->timer_count_left)) { - cpu_mytimer->timer_start_count++; - _mytimer->cpu = cpu; - mod_timer(&_mytimer->_timer, jiffies + TIMER_DELAY); - } } extern int not_idle[5], all_idle[5], non_idle_found[5][5]; @@ -105,10 +93,13 @@ static void wq_function(struct work_struct *_work) int cpu = raw_smp_processor_id(), i; int cpus = num_present_cpus(); struct mywork *_mywork = container_of(_work, struct mywork, _work); + struct mytimer *_mytimer = &per_cpu(_cpu_mytimer, _mywork->cpu); /* Find current cpu id */ per_cpu(cpu_work_fn_count, cpu)++; + mdelay(20); + /* work is queued and processed by same cpu */ if (_mywork->cpu == cpu) per_cpu(cpu_own_work_count, cpu)++; @@ -145,6 +136,13 @@ static void wq_function(struct work_struct *_work) pr_info("found non idle: src: %d, dest: %d, count: %d\n", cpu, i, non_idle_found[cpu][i]); } + return; + } + + _mytimer->_timer.expires = jiffies + TIMER_DELAY; + if (--(_mytimer->timer_count_left)) { + _mytimer->timer_start_count++; + add_timer_on(&_mytimer->_timer, _mytimer->cpu); } } @@ -165,6 +163,7 @@ static void wq_per_cpu(struct work_struct *_work) _mytimer = &per_cpu(_cpu_mytimer, cpu); timer = &_mytimer->_timer; init_timer(timer); + timer->expires = jiffies + TIMER_DELAY; timer->data = (unsigned long)_mytimer; timer->function = timer_fn; _mytimer->timer_count_left = total_works_per_timer; @@ -172,7 +171,7 @@ static void wq_per_cpu(struct work_struct *_work) _mytimer->timer_fn_count = 0; _mytimer->timer_migration_count = 0; _mytimer->cpu = cpu; - mod_timer(timer, jiffies + TIMER_DELAY); + add_timer_on(timer, cpu); } static void init_globals(void) @@ -207,15 +206,17 @@ static int __init wq_module_init(void) return 0; } - _myworks = kmalloc(cpus * total_works_per_timer * sizeof(*_myworks), + _myworks = kmalloc(cpus * sizeof(*_myworks), GFP_KERNEL); if (!_myworks) { pr_err("Failed to allocate work\n"); return 0; } - for (i = 0; i < cpus * total_works_per_timer; i++) + for (i = 0; i < cpus; i++) { INIT_WORK(&_myworks[i]._work, wq_function); + _myworks[i].cpu = i; + } init_globals(); for_each_present_cpu(cpu) { @@ -223,7 +224,7 @@ static int __init wq_module_init(void) queue_work_on(cpu, gwq, &gwork[cpu]); } - wait_for_completion(&wq_complete); + wait_for_completion_interruptible(&wq_complete); return 0; } @@ -231,14 +232,16 @@ static void __exit wq_module_exit(void) { int cpu; struct workqueue_struct *wq; - - kfree(_myworks); + struct mytimer *_mytimer; for_each_present_cpu(cpu) { + _mytimer = &per_cpu(_cpu_mytimer, cpu); + del_timer(&_mytimer->_timer); wq = per_cpu(cpu_wq, cpu); destroy_workqueue(wq); } + kfree(_myworks); kfree(gwork); destroy_workqueue(gwq); } -- cgit v1.2.3