From 80b4c191cbea7c104e825a4e7e94980dcb33fee0 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 4 Feb 2002 19:14:56 -0800 Subject: v2.4.7.1 -> v2.4.7.2 - Kai Germaschewski: ISDN updates - David Miller: sparc and network updates - Andrea Arcangeli, Maksim Krasnyanskiy: tasklet fixes - Stelian Pop: Motion Eye camera driver update - Jens Axboe: DAC960 update --- include/linux/interrupt.h | 54 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 10 deletions(-) (limited to 'include/linux/interrupt.h') diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 5e8c520f42bf..d5e7e9acf99c 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -118,7 +118,7 @@ struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(1), func, data } enum { TASKLET_STATE_SCHED, /* Tasklet is scheduled for execution */ - TASKLET_STATE_RUN /* Tasklet is running */ + TASKLET_STATE_RUN /* Tasklet is running (SMP only) */ }; struct tasklet_head @@ -129,34 +129,68 @@ struct tasklet_head extern struct tasklet_head tasklet_vec[NR_CPUS]; extern struct tasklet_head tasklet_hi_vec[NR_CPUS]; -#define tasklet_trylock(t) (!test_and_set_bit(TASKLET_STATE_RUN, &(t)->state)) -#define tasklet_unlock(t) do { smp_mb__before_clear_bit(); clear_bit(TASKLET_STATE_RUN, &(t)->state); } while(0) -#define tasklet_unlock_wait(t) while (test_bit(TASKLET_STATE_RUN, &(t)->state)) { barrier(); } +#ifdef CONFIG_SMP +static inline int tasklet_trylock(struct tasklet_struct *t) +{ + return !test_and_set_bit(TASKLET_STATE_RUN, &(t)->state); +} + +static inline void tasklet_unlock(struct tasklet_struct *t) +{ + smp_mb__before_clear_bit(); + clear_bit(TASKLET_STATE_RUN, &(t)->state); +} + +static inline void tasklet_unlock_wait(struct tasklet_struct *t) +{ + while (test_bit(TASKLET_STATE_RUN, &(t)->state)) { barrier(); } +} +#else +#define tasklet_trylock(t) 1 +#define tasklet_unlock_wait(t) do { } while (0) +#define tasklet_unlock(t) do { } while (0) +#endif + +extern void FASTCALL(__tasklet_schedule(struct tasklet_struct *t)); + +static inline void tasklet_schedule(struct tasklet_struct *t) +{ + if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) + __tasklet_schedule(t); +} + +extern void FASTCALL(__tasklet_hi_schedule(struct tasklet_struct *t)); + +static inline void tasklet_hi_schedule(struct tasklet_struct *t) +{ + if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) + __tasklet_hi_schedule(t); +} -extern void tasklet_schedule(struct tasklet_struct *t); -extern void tasklet_hi_schedule(struct tasklet_struct *t); 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); + smp_mb(); } static inline void tasklet_enable(struct tasklet_struct *t) { - if (atomic_dec_and_test(&t->count)) - tasklet_schedule(t); + smp_mb__before_atomic_dec(); + atomic_dec(&t->count); } static inline void tasklet_hi_enable(struct tasklet_struct *t) { - if (atomic_dec_and_test(&t->count)) - tasklet_hi_schedule(t); + smp_mb__before_atomic_dec(); + atomic_dec(&t->count); } extern void tasklet_kill(struct tasklet_struct *t); -- cgit v1.2.3