diff options
Diffstat (limited to 'kernel/sched/core.c')
| -rw-r--r-- | kernel/sched/core.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index a674c7db2f29..d8d76a65cfdd 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c | |||
| @@ -396,6 +396,18 @@ static bool set_nr_if_polling(struct task_struct *p) | |||
| 396 | #endif | 396 | #endif |
| 397 | #endif | 397 | #endif |
| 398 | 398 | ||
| 399 | /** | ||
| 400 | * wake_q_add() - queue a wakeup for 'later' waking. | ||
| 401 | * @head: the wake_q_head to add @task to | ||
| 402 | * @task: the task to queue for 'later' wakeup | ||
| 403 | * | ||
| 404 | * Queue a task for later wakeup, most likely by the wake_up_q() call in the | ||
| 405 | * same context, _HOWEVER_ this is not guaranteed, the wakeup can come | ||
| 406 | * instantly. | ||
| 407 | * | ||
| 408 | * This function must be used as-if it were wake_up_process(); IOW the task | ||
| 409 | * must be ready to be woken at this location. | ||
| 410 | */ | ||
| 399 | void wake_q_add(struct wake_q_head *head, struct task_struct *task) | 411 | void wake_q_add(struct wake_q_head *head, struct task_struct *task) |
| 400 | { | 412 | { |
| 401 | struct wake_q_node *node = &task->wake_q; | 413 | struct wake_q_node *node = &task->wake_q; |
| @@ -405,10 +417,11 @@ void wake_q_add(struct wake_q_head *head, struct task_struct *task) | |||
| 405 | * its already queued (either by us or someone else) and will get the | 417 | * its already queued (either by us or someone else) and will get the |
| 406 | * wakeup due to that. | 418 | * wakeup due to that. |
| 407 | * | 419 | * |
| 408 | * This cmpxchg() executes a full barrier, which pairs with the full | 420 | * In order to ensure that a pending wakeup will observe our pending |
| 409 | * barrier executed by the wakeup in wake_up_q(). | 421 | * state, even in the failed case, an explicit smp_mb() must be used. |
| 410 | */ | 422 | */ |
| 411 | if (cmpxchg(&node->next, NULL, WAKE_Q_TAIL)) | 423 | smp_mb__before_atomic(); |
| 424 | if (cmpxchg_relaxed(&node->next, NULL, WAKE_Q_TAIL)) | ||
| 412 | return; | 425 | return; |
| 413 | 426 | ||
| 414 | get_task_struct(task); | 427 | get_task_struct(task); |
