Looking back on stuff which happened a long time ago, there's a
possibility that there's an ordering issue with set_current_state.
Please note that this is affects _all_ 2.4 architectures.
I think this was discussed about 6 months ago, so I'm surprised this
hasn't made it into the 2.4.2x kernel (or no one else has seen the
problem.)
Please note that since I don't track 2.4 kernels currently, I've no
idea whether 2.4.21-pre/rc has this fix. (This means if Marcelo
drops or ignores the fix, it won't get re-sent.) Certainly gcc 3
requires this patch. I've not heard of gcc 2.95.x tripping over
this problem though.
The problem area is:
#define __set_task_state(tsk, state_value) \
do { (tsk)->state = (state_value); } while (0)
#ifdef CONFIG_SMP
#define set_task_state(tsk, state_value) \
set_mb((tsk)->state, (state_value))
#else
#define set_task_state(tsk, state_value) \
__set_task_state((tsk), (state_value))
#endif
#define __set_current_state(state_value) \
do { current->state = (state_value); } while (0)
#ifdef CONFIG_SMP
#define set_current_state(state_value) \
set_mb(current->state, (state_value))
#else
#define set_current_state(state_value) \
__set_current_state(state_value)
#endif
As they currently stand, there is no guarantee that the assignment to
"->state" occurs before the condition in wait_event is processed.
The attached patch should fix your problem. It should be applied to
2.4.2x. All architectures which do not provide set_mb() need to be
fixed.
--- ref/include/linux/sched.h Wed Mar 19 15:54:45 2003
+++ linux/include/linux/sched.h Wed May 14 09:45:31 2003
@@ -94,23 +94,13 @@
#define __set_task_state(tsk, state_value) \
do { (tsk)->state = (state_value); } while (0)
-#ifdef CONFIG_SMP
#define set_task_state(tsk, state_value) \
set_mb((tsk)->state, (state_value))
-#else
-#define set_task_state(tsk, state_value) \
- __set_task_state((tsk), (state_value))
-#endif
#define __set_current_state(state_value) \
do { current->state = (state_value); } while (0)
-#ifdef CONFIG_SMP
#define set_current_state(state_value) \
set_mb(current->state, (state_value))
-#else
-#define set_current_state(state_value) \
- __set_current_state(state_value)
-#endif
/*
* Scheduling policies
--- ref/include/asm-arm/system.h Wed Sep 11 17:30:52 2002
+++ linux/include/asm-arm/system.h Wed May 14 09:46:20 2003
@@ -46,6 +46,8 @@
#define mb() __asm__ __volatile__ ("" : : : "memory")
#define rmb() mb()
#define wmb() mb()
+#define set_mb(var, value) do { var = value; mb(); } while (0)
+#define set_wmb(var, value) do { var = value; wmb(); } while (0)
#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
#define prepare_to_switch() do { } while(0)
-- Russell King (rmk@arm.linux.org.uk) The developer of ARM Linux http://www.arm.linux.org.uk/personal/aboutme.html - 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/