--- 2.4.4pre2aa/include/asm-alpha/atomic.h.~1~ Tue Nov 28 18:40:01 2000 +++ 2.4.4pre2aa/include/asm-alpha/atomic.h Fri Apr 13 04:17:16 2001 @@ -106,4 +106,9 @@ #define atomic_inc(v) atomic_add(1,(v)) #define atomic_dec(v) atomic_sub(1,(v)) +#define smp_mb__before_atomic_inc() smp_mb() +#define smp_mb__after_atomic_inc() smp_mb() +#define smp_mb__before_atomic_dec() smp_mb() +#define smp_mb__after_atomic_dec() smp_mb() + #endif /* _ALPHA_ATOMIC_H */ --- 2.4.4pre2aa/include/asm-i386/atomic.h.~1~ Thu Apr 12 21:42:17 2001 +++ 2.4.4pre2aa/include/asm-i386/atomic.h Fri Apr 13 05:09:17 2001 @@ -42,6 +42,15 @@ */ #define atomic_set(v,i) (((v)->counter) = (i)) +/* + * It maybe we need an explicit serialization across inc/dec on + * recent chips, if not then just replace this with a barrier(). + */ +#define smp_mb__before_atomic_inc() smp_mb() +#define smp_mb__after_atomic_inc() smp_mb() +#define smp_mb__before_atomic_dec() smp_mb() +#define smp_mb__after_atomic_dec() smp_mb() + /** * atomic_add - add integer to atomic variable * @i: integer value to add --- 2.4.4pre2aa/include/linux/interrupt.h.~1~ Thu Apr 12 21:42:17 2001 +++ 2.4.4pre2aa/include/linux/interrupt.h Fri Apr 13 04:41:19 2001 @@ -186,16 +186,20 @@ static inline void tasklet_disable_nosync(struct tasklet_struct *t) { atomic_inc(&t->count); + smp_mb__after_atomic_inc(); } static inline void tasklet_disable(struct tasklet_struct *t) { tasklet_disable_nosync(t); tasklet_unlock_wait(t); + /* Make sure not to speculate reads until the tasklet resigns. */ + smp_rmb(); } static inline void tasklet_enable(struct tasklet_struct *t) { + smp_mb__before_atomic_dec(); atomic_dec(&t->count); } --- 2.4.4pre2aa/kernel/softirq.c.~1~ Thu Apr 12 17:05:40 2001 +++ 2.4.4pre2aa/kernel/softirq.c Fri Apr 13 04:35:54 2001 @@ -153,9 +153,15 @@ t->func(t->data); /* - * talklet_trylock() uses test_and_set_bit that imply + * talklet_trylock() uses test_and_set_bit that _just_ imply * an mb when it returns zero, thus we need the explicit * mb only here: while closing the critical section. + * + * On UP the barrier() in not necessary because f->func + * cannot be reordered by the compiler anyways because + * of the C language. Unless the compiler is doing something + * stupid dropping the #ifdef wouldn't make any difference in the + * generatd asm though (the #ifdef is mostly a documenetation issue). */ #ifdef CONFIG_SMP smp_mb__before_clear_bit(); @@ -163,6 +169,13 @@ tasklet_unlock(t); continue; } + /* + * NOTE: here we don't need the smb_mb() because the tasklet_unlock() + * write depends on the read of the &t->count that is in turn _the_ + * variable that the lock is serializing. The CPU isn't allowed to + * write to the memory before we checked t->count is not zero and + * by that time we don't need the lock any longer. + */ tasklet_unlock(t); } local_irq_disable(); @@ -197,6 +210,9 @@ clear_bit(TASKLET_STATE_SCHED, &t->state); t->func(t->data); +#ifdef CONFIG_SMP + smp_mb__before_clear_bit(); +#endif tasklet_unlock(t); continue; }