Re: [PATCH] fix loop with disabled tasklets

From: Momchil Velikov (velco@fadata.bg)
Date: Sun Nov 11 2001 - 10:56:22 EST


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
-
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/



This archive was generated by hypermail 2b29 : Thu Nov 15 2001 - 21:00:26 EST