btw Here is an idea. May be we should reschedule tasklet on the same cpu it's running on.
It should probably improve cache usage and stuff.
I'm thinking about something like this.
static inline void tasklet_schedule(struct tasklet_struct *t)
{
if (test_bit(TASKLET_STATE_RUN, &t->state)) {
set_bit(TASKLET_NEED_RESCHED, &t->state);
} else if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) {
int cpu = smp_processor_id();
unsigned long flags;
local_irq_save(flags);
t->next = tasklet_vec[cpu].list;
tasklet_vec[cpu].list = t;
cpu_raise_softirq(cpu, TASKLET_SOFTIRQ);
local_irq_restore(flags);
}
}
static void tasklet_action(struct softirq_action *a)
{
int cpu = smp_processor_id();
struct tasklet_struct *list;
local_irq_disable();
list = tasklet_vec[cpu].list;
tasklet_vec[cpu].list = NULL;
local_irq_enable();
while (list) {
struct tasklet_struct *t = list;
list = list->next;
if (tasklet_trylock(t)) {
if (!atomic_read(&t->count)) {
if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
BUG();
t->func(t->data);
tasklet_unlock(t);
if (test_and_clear_bit(TASKLET_NEED_RESCHED, &t->state)
goto resched;
continue;
}
tasklet_unlock(t);
}
resched:
local_irq_disable();
t->next = tasklet_vec[cpu].list;
tasklet_vec[cpu].list = t;
cpu_raise_softirq(cpu, TASKLET_SOFTIRQ);
local_irq_enable();
}
}
There is small window there but this is just rfc. So if tasklet is already running we set NEED_RESCHED bit and tasklet_action
reschedules tasklet on the same cpu. (currently we may reschedule it on anther cpu).
Comments ?
Max
Maksim Krasnyanskiy
Senior Kernel Engineer
Qualcomm Incorporated
maxk@qualcomm.com
http://bluez.sf.net
http://vtun.sf.net
-
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/