Re: [PATCH] fix loop with disabled tasklets

Momchil Velikov
2001-11-11T15:59:40Z

Mathijs,

You may want to have a look at the following patches (tested by visual
inspection):

--- softirq.c.orig Sun Nov 11 16:42:14 2001
+++ softirq.c Sun Nov 11 16:59:44 2001
@@ -188,22 +188,17 @@ static void tasklet_action(struct softir

list = list->next;

+ if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
+ BUG();
+
if (tasklet_trylock(t)) {
- if (!atomic_read(&t->count)) {
- if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
- BUG();
+ if (!atomic_read(&t->count))
t->func(t->data);
- tasklet_unlock(t);
- continue;
- }
tasklet_unlock(t);
+ continue;
}

- local_irq_disable();
- t->next = tasklet_vec[cpu].list;
- tasklet_vec[cpu].list = t;
- __cpu_raise_softirq(cpu, TASKLET_SOFTIRQ);
- local_irq_enable();
+ tasklet_schedule(t);
}
}

@@ -222,22 +217,17 @@ static void tasklet_hi_action(struct sof

list = list->next;

+ if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
+ BUG();
+
if (tasklet_trylock(t)) {
- if (!atomic_read(&t->count)) {
- if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
- BUG();
+ if (!atomic_read(&t->count))
t->func(t->data);
- tasklet_unlock(t);
- continue;
- }
tasklet_unlock(t);
+ continue;
}

- local_irq_disable();
- t->next = tasklet_hi_vec[cpu].list;
- tasklet_hi_vec[cpu].list = t;
- __cpu_raise_softirq(cpu, HI_SOFTIRQ);
- local_irq_enable();
+ tasklet_hi_schedule(t);
}
}

--- interrupt.h.orig Sun Nov 11 16:49:05 2001
+++ interrupt.h Sun Nov 11 17:28:08 2001
@@ -185,13 +185,15 @@ static inline void tasklet_disable(struc
static inline void tasklet_enable(struct tasklet_struct *t)
{
smp_mb__before_atomic_dec();
- atomic_dec(&t->count);
+ if (atomic_dec_and_test(&t->count))
+ tasklet_schedule(t);
}

static inline void tasklet_hi_enable(struct tasklet_struct *t)
{
smp_mb__before_atomic_dec();
- atomic_dec(&t->count);
+ if (atomic_dec_and_test(&t->count))
+ tasklet_hi_schedule(t);
}

extern void tasklet_kill(struct tasklet_struct *t);

Regards,
-velco