[lkml]   [2003]   [Aug]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
Patch in this message
SubjectRace condition in 2.4 tasklet handling
 It's a similar to race condition spotted in i386 interrupt code.  The
race exists between tasklet_[hi_]action() and tasklet_disable().
Again, memory-ordered synchronization is used between
tasklet_struct.count and tasklet_struct.state.

tasklet_disable() is find because there's an smp_mb() at the end of
tasklet_disable_nosync(); however, in tasklet_action(), there is no
mb() between tasklet_trylock(t) and atomic_read(&t->count). This
won't cause any trouble on architectures which orders memory accesses
around atomic operations such (including x86), but on architectures
which don't, a tasklet can be executing on another cpu on return from

Adding smp_mb__after_test_and_set_bit() at the end of
tasklet_trylock() should remedy the situation. As
smp_mb__{before|after}_test_and_set_bit() don't exist yet, I'm
attaching a patch which adds smp_mb__after_clear_bit(). The patch is
against 2.4.21.

P.S. Please comment on the addition of

P.P.S. One thing I don't really understand is the uses of smp_mb() at
the end of tasklet_disable() and smp_mb__before_atomic_dec() inside
tasklet_enable(). Can anybody tell me what those are for?

# This is a BitKeeper generated patch for the following project:
# Project Name: linux
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.3 -> 1.4
# include/linux/interrupt.h 1.1 -> 1.2
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/08/23 1.4
# - tasklet race fix.
# --------------------------------------------
diff -Nru a/include/linux/interrupt.h b/include/linux/interrupt.h
--- a/include/linux/interrupt.h Sat Aug 23 11:52:03 2003
+++ b/include/linux/interrupt.h Sat Aug 23 11:52:03 2003
@@ -134,7 +134,10 @@
static inline int tasklet_trylock(struct tasklet_struct *t)
- return !test_and_set_bit(TASKLET_STATE_RUN, &(t)->state);
+ int ret;
+ ret = !test_and_set_bit(TASKLET_STATE_RUN, &(t)->state);
+ smp_mb__after_clear_bit();
+ return ret;

static inline void tasklet_unlock(struct tasklet_struct *t)
 \ /
  Last update: 2005-03-22 13:48    [W:0.307 / U:0.944 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site