diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-02-15 09:05:26 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-02-15 09:05:26 -0800 |
commit | e9e3b3002fc3c9ef665628bd85a8c1b5a3424f23 (patch) | |
tree | a3f867a79cbafb9b5144dad4339e007780c60330 /kernel | |
parent | e525de3ab04621d227330aa82cd4073c0b0f3579 (diff) | |
parent | 2dd6fd2e999774041397f2a7da2e1d30b3a27c3a (diff) | |
download | linux-e9e3b3002fc3c9ef665628bd85a8c1b5a3424f23.tar.bz2 |
Merge branch 'locking-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull locking fixes from Ingo Molnar:
"This contains two qspinlock fixes and three documentation and comment
fixes"
* 'locking-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
locking/semaphore: Update the file path in documentation
locking/atomic/bitops: Document and clarify ordering semantics for failed test_and_{}_bit()
locking/qspinlock: Ensure node->count is updated before initialising node
locking/qspinlock: Ensure node is initialised before updating prev->next
Documentation/locking/mutex-design: Update to reflect latest changes
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/locking/qspinlock.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/kernel/locking/qspinlock.c b/kernel/locking/qspinlock.c index 38ece035039e..d880296245c5 100644 --- a/kernel/locking/qspinlock.c +++ b/kernel/locking/qspinlock.c @@ -379,6 +379,14 @@ queue: tail = encode_tail(smp_processor_id(), idx); node += idx; + + /* + * Ensure that we increment the head node->count before initialising + * the actual node. If the compiler is kind enough to reorder these + * stores, then an IRQ could overwrite our assignments. + */ + barrier(); + node->locked = 0; node->next = NULL; pv_init_node(node); @@ -408,14 +416,15 @@ queue: */ if (old & _Q_TAIL_MASK) { prev = decode_tail(old); + /* - * The above xchg_tail() is also a load of @lock which - * generates, through decode_tail(), a pointer. The address - * dependency matches the RELEASE of xchg_tail() such that - * the subsequent access to @prev happens after. + * We must ensure that the stores to @node are observed before + * the write to prev->next. The address dependency from + * xchg_tail is not sufficient to ensure this because the read + * component of xchg_tail is unordered with respect to the + * initialisation of @node. */ - - WRITE_ONCE(prev->next, node); + smp_store_release(&prev->next, node); pv_wait_node(node, prev); arch_mcs_spin_lock_contended(&node->locked); |