lkml.org 
[lkml]   [2006]   [Nov]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[RFC][PATCH] Add do_not_call_when_idle option to timer and workqueue

Add a new flag to timers to allow "Do not call when Idle" mode.
Export this sort of soft timer over workqueues and use it in ondemand governor.

This patch avoids the periodic ondemand timer invocations in
Dynamic Tick kernels.

This can be used in various other kernel timers that end up setting up
unnecessary timers during idle.

Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>

Index: linux-2.6.19-rc-mm/include/linux/timer.h
===================================================================
--- linux-2.6.19-rc-mm.orig/include/linux/timer.h 2006-11-13 15:06:26.000000000 -0800
+++ linux-2.6.19-rc-mm/include/linux/timer.h 2006-11-13 16:01:03.000000000 -0800
@@ -8,6 +8,8 @@

struct tvec_t_base_s;

+#define TIMER_FLAG_NOT_IN_IDLE (0x1)
+
struct timer_list {
struct list_head entry;
unsigned long expires;
@@ -16,6 +18,7 @@
unsigned long data;

struct tvec_t_base_s *base;
+ int flags;
#ifdef CONFIG_TIMER_STATS
void *start_site;
char start_comm[16];
@@ -30,6 +33,7 @@
.expires = (_expires), \
.data = (_data), \
.base = &boot_tvec_bases, \
+ .flags = 0, \
}

#define DEFINE_TIMER(_name, _function, _expires, _data) \
Index: linux-2.6.19-rc-mm/include/linux/workqueue.h
===================================================================
--- linux-2.6.19-rc-mm.orig/include/linux/workqueue.h 2006-11-13 15:06:26.000000000 -0800
+++ linux-2.6.19-rc-mm/include/linux/workqueue.h 2006-11-13 16:01:03.000000000 -0800
@@ -65,6 +65,8 @@
extern int FASTCALL(queue_delayed_work(struct workqueue_struct *wq, struct work_struct *work, unsigned long delay));
extern int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
struct work_struct *work, unsigned long delay);
+extern int queue_soft_delayed_work_on(int cpu, struct workqueue_struct *wq,
+ struct work_struct *work, unsigned long delay);
extern void FASTCALL(flush_workqueue(struct workqueue_struct *wq));

extern int FASTCALL(schedule_work(struct work_struct *work));
Index: linux-2.6.19-rc-mm/kernel/timer.c
===================================================================
--- linux-2.6.19-rc-mm.orig/kernel/timer.c 2006-11-13 15:06:26.000000000 -0800
+++ linux-2.6.19-rc-mm/kernel/timer.c 2006-11-13 16:01:03.000000000 -0800
@@ -639,6 +639,8 @@
j = base->timer_jiffies & TVR_MASK;
do {
list_for_each_entry(nte, base->tv1.vec + j, entry) {
+ if (nte->flags & TIMER_FLAG_NOT_IN_IDLE)
+ continue;
expires = nte->expires;
found = nte;
if (j < (base->timer_jiffies & TVR_MASK))
Index: linux-2.6.19-rc-mm/kernel/workqueue.c
===================================================================
--- linux-2.6.19-rc-mm.orig/kernel/workqueue.c 2006-11-13 15:06:26.000000000 -0800
+++ linux-2.6.19-rc-mm/kernel/workqueue.c 2006-11-13 16:01:03.000000000 -0800
@@ -196,6 +196,20 @@
}
EXPORT_SYMBOL_GPL(queue_delayed_work_on);

+int queue_soft_delayed_work_on(int cpu, struct workqueue_struct *wq,
+ struct work_struct *work, unsigned long delay)
+{
+ int ret;
+ struct timer_list *timer = &work->timer;
+ ret = queue_delayed_work_on(cpu, wq, work, delay);
+ if (ret) {
+ timer->flags |= TIMER_FLAG_NOT_IN_IDLE;
+ }
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(queue_soft_delayed_work_on);
+
static void run_workqueue(struct cpu_workqueue_struct *cwq)
{
unsigned long flags;
Index: linux-2.6.19-rc-mm/drivers/cpufreq/cpufreq_ondemand.c
===================================================================
--- linux-2.6.19-rc-mm.orig/drivers/cpufreq/cpufreq_ondemand.c 2006-11-13 15:58:04.000000000 -0800
+++ linux-2.6.19-rc-mm/drivers/cpufreq/cpufreq_ondemand.c 2006-11-21 12:23:15.000000000 -0800
@@ -446,7 +448,7 @@
dbs_info->freq_lo,
CPUFREQ_RELATION_H);
}
- queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay);
+ queue_soft_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay);
}

static inline void dbs_timer_init(unsigned int cpu)
@@ -456,9 +458,9 @@
int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
delay -= jiffies % delay;

ondemand_powersave_bias_init();
INIT_WORK(&dbs_info->work, do_dbs_timer, NULL);
- queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay);
+ queue_soft_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay);
}

static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
\
 
 \ /
  Last update: 2006-11-22 01:55    [W:0.150 / U:0.612 seconds]
©2003-2014 Jasper Spaans. Advertise on this site