|
@@ -262,20 +262,9 @@ extern char ___assert_task_state[1 - 2*!!(
|
|
|
#define set_task_state(tsk, state_value) \
|
|
|
do { \
|
|
|
(tsk)->task_state_change = _THIS_IP_; \
|
|
|
- smp_store_mb((tsk)->state, (state_value)); \
|
|
|
+ smp_store_mb((tsk)->state, (state_value)); \
|
|
|
} while (0)
|
|
|
|
|
|
-/*
|
|
|
- * set_current_state() includes a barrier so that the write of current->state
|
|
|
- * is correctly serialised wrt the caller's subsequent test of whether to
|
|
|
- * actually sleep:
|
|
|
- *
|
|
|
- * set_current_state(TASK_UNINTERRUPTIBLE);
|
|
|
- * if (do_i_need_to_sleep())
|
|
|
- * schedule();
|
|
|
- *
|
|
|
- * If the caller does not need such serialisation then use __set_current_state()
|
|
|
- */
|
|
|
#define __set_current_state(state_value) \
|
|
|
do { \
|
|
|
current->task_state_change = _THIS_IP_; \
|
|
@@ -284,11 +273,19 @@ extern char ___assert_task_state[1 - 2*!!(
|
|
|
#define set_current_state(state_value) \
|
|
|
do { \
|
|
|
current->task_state_change = _THIS_IP_; \
|
|
|
- smp_store_mb(current->state, (state_value)); \
|
|
|
+ smp_store_mb(current->state, (state_value)); \
|
|
|
} while (0)
|
|
|
|
|
|
#else
|
|
|
|
|
|
+/*
|
|
|
+ * @tsk had better be current, or you get to keep the pieces.
|
|
|
+ *
|
|
|
+ * The only reason is that computing current can be more expensive than
|
|
|
+ * using a pointer that's already available.
|
|
|
+ *
|
|
|
+ * Therefore, see set_current_state().
|
|
|
+ */
|
|
|
#define __set_task_state(tsk, state_value) \
|
|
|
do { (tsk)->state = (state_value); } while (0)
|
|
|
#define set_task_state(tsk, state_value) \
|
|
@@ -299,11 +296,34 @@ extern char ___assert_task_state[1 - 2*!!(
|
|
|
* is correctly serialised wrt the caller's subsequent test of whether to
|
|
|
* actually sleep:
|
|
|
*
|
|
|
+ * for (;;) {
|
|
|
* set_current_state(TASK_UNINTERRUPTIBLE);
|
|
|
- * if (do_i_need_to_sleep())
|
|
|
- * schedule();
|
|
|
+ * if (!need_sleep)
|
|
|
+ * break;
|
|
|
+ *
|
|
|
+ * schedule();
|
|
|
+ * }
|
|
|
+ * __set_current_state(TASK_RUNNING);
|
|
|
+ *
|
|
|
+ * If the caller does not need such serialisation (because, for instance, the
|
|
|
+ * condition test and condition change and wakeup are under the same lock) then
|
|
|
+ * use __set_current_state().
|
|
|
+ *
|
|
|
+ * The above is typically ordered against the wakeup, which does:
|
|
|
+ *
|
|
|
+ * need_sleep = false;
|
|
|
+ * wake_up_state(p, TASK_UNINTERRUPTIBLE);
|
|
|
+ *
|
|
|
+ * Where wake_up_state() (and all other wakeup primitives) imply enough
|
|
|
+ * barriers to order the store of the variable against wakeup.
|
|
|
+ *
|
|
|
+ * Wakeup will do: if (@state & p->state) p->state = TASK_RUNNING, that is,
|
|
|
+ * once it observes the TASK_UNINTERRUPTIBLE store the waking CPU can issue a
|
|
|
+ * TASK_RUNNING store which can collide with __set_current_state(TASK_RUNNING).
|
|
|
+ *
|
|
|
+ * This is obviously fine, since they both store the exact same value.
|
|
|
*
|
|
|
- * If the caller does not need such serialisation then use __set_current_state()
|
|
|
+ * Also see the comments of try_to_wake_up().
|
|
|
*/
|
|
|
#define __set_current_state(state_value) \
|
|
|
do { current->state = (state_value); } while (0)
|