|
@@ -73,7 +73,7 @@ static void __prepare_to_swait(struct swait_queue_head *q, struct swait_queue *w
|
|
|
{
|
|
|
wait->task = current;
|
|
|
if (list_empty(&wait->task_list))
|
|
|
- list_add(&wait->task_list, &q->task_list);
|
|
|
+ list_add_tail(&wait->task_list, &q->task_list);
|
|
|
}
|
|
|
|
|
|
void prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait, int state)
|
|
@@ -89,12 +89,24 @@ EXPORT_SYMBOL(prepare_to_swait);
|
|
|
|
|
|
long prepare_to_swait_event(struct swait_queue_head *q, struct swait_queue *wait, int state)
|
|
|
{
|
|
|
- if (signal_pending_state(state, current))
|
|
|
- return -ERESTARTSYS;
|
|
|
+ unsigned long flags;
|
|
|
+ long ret = 0;
|
|
|
|
|
|
- prepare_to_swait(q, wait, state);
|
|
|
+ raw_spin_lock_irqsave(&q->lock, flags);
|
|
|
+ if (unlikely(signal_pending_state(state, current))) {
|
|
|
+ /*
|
|
|
+ * See prepare_to_wait_event(). TL;DR, subsequent swake_up()
|
|
|
+ * must not see us.
|
|
|
+ */
|
|
|
+ list_del_init(&wait->task_list);
|
|
|
+ ret = -ERESTARTSYS;
|
|
|
+ } else {
|
|
|
+ __prepare_to_swait(q, wait);
|
|
|
+ set_current_state(state);
|
|
|
+ }
|
|
|
+ raw_spin_unlock_irqrestore(&q->lock, flags);
|
|
|
|
|
|
- return 0;
|
|
|
+ return ret;
|
|
|
}
|
|
|
EXPORT_SYMBOL(prepare_to_swait_event);
|
|
|
|