summaryrefslogtreecommitdiff
path: root/kernel/locking/rwsem-xadd.c
diff options
context:
space:
mode:
authorMarcel Ziswiler <marcel.ziswiler@toradex.com>2019-03-28 14:32:06 +0100
committerMarcel Ziswiler <marcel.ziswiler@toradex.com>2019-03-28 14:32:06 +0100
commit32aca03c2ce868d3412da0bb6ce6798c7bea357e (patch)
tree01630dc4a6935df99bf7d11d34ff8d384fed86e2 /kernel/locking/rwsem-xadd.c
parentcfbbc7703fff59c67761c93a8b1de29a79f9841c (diff)
parent60771fc402877163d07569addadcf18b86acb455 (diff)
Merge tag 'v4.9.166' into 4.9-2.3.x-imx
This is the 4.9.166 stable release
Diffstat (limited to 'kernel/locking/rwsem-xadd.c')
-rw-r--r--kernel/locking/rwsem-xadd.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c
index a4112dfcd0fb..be06c45cbe4f 100644
--- a/kernel/locking/rwsem-xadd.c
+++ b/kernel/locking/rwsem-xadd.c
@@ -195,15 +195,22 @@ static void __rwsem_mark_wake(struct rw_semaphore *sem,
woken++;
tsk = waiter->task;
- wake_q_add(wake_q, tsk);
+ get_task_struct(tsk);
list_del(&waiter->list);
/*
- * Ensure that the last operation is setting the reader
+ * Ensure calling get_task_struct() before setting the reader
* waiter to nil such that rwsem_down_read_failed() cannot
* race with do_exit() by always holding a reference count
* to the task to wakeup.
*/
smp_store_release(&waiter->task, NULL);
+ /*
+ * Ensure issuing the wakeup (either by us or someone else)
+ * after setting the reader waiter to nil.
+ */
+ wake_q_add(wake_q, tsk);
+ /* wake_q_add() already take the task ref */
+ put_task_struct(tsk);
}
adjustment = woken * RWSEM_ACTIVE_READ_BIAS - adjustment;