aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2013-01-18 14:10:12 +0530
committerViresh Kumar <viresh.kumar@linaro.org>2013-01-18 14:10:12 +0530
commitf555d61e4d5b19a4b81c8a56e66cafaee0ede45e (patch)
tree6cf84a9a4a48d195571e16a136f92df569248c35
parent8f71839769dda9c5990fa9eb108cd5e9d482177a (diff)
workqueue: Start timer from work
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
-rw-r--r--workqueue.c49
1 files 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 <linux/cpumask.h>
#include <linux/completion.h>
+#include <linux/delay.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/percpu.h>
@@ -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);
}