aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-24 07:36:16 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-24 07:36:16 -0400
commit2da2ca24a38f0200111e3b8823c08d02cb59d362 (patch)
treecc56a909e00017ed1a39175e60f4fb922c01f8f0
parenta43de489934cadcbc4cc08a6590fdcc833768461 (diff)
parent6cc65be4f6f2a7186af8f3e09900787c7912dad2 (diff)
Merge branch 'locking-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull locking fixes from Thomas Gleixner: "A set of fixes and updates for the locking code: - Prevent lockdep from updating irq state within its own code and thereby confusing itself. - Buid fix for older GCCs which mistreat anonymous unions - Add a missing lockdep annotation in down_read_non_onwer() which causes up_read_non_owner() to emit a lockdep splat - Remove the custom alpha dec_and_lock() implementation which is incorrect in terms of ordering and use the generic one. The remaining two commits are not strictly fixes. They provide irqsave variants of atomic_dec_and_lock() and refcount_dec_and_lock(). These are required to merge the relevant updates and cleanups into different maintainer trees for 4.19, so routing them into mainline without actual users is the sanest approach. They should have been in -rc1, but last weekend I took the liberty to just avoid computers in order to regain some mental sanity" * 'locking-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: locking/qspinlock: Fix build for anonymous union in older GCC compilers locking/lockdep: Do not record IRQ state within lockdep code locking/rwsem: Fix up_read_non_owner() warning with DEBUG_RWSEMS locking/refcounts: Implement refcount_dec_and_lock_irqsave() atomic: Add irqsave variant of atomic_dec_and_lock() alpha: Remove custom dec_and_lock() implementation
-rw-r--r--arch/alpha/Kconfig5
-rw-r--r--arch/alpha/lib/Makefile2
-rw-r--r--arch/alpha/lib/dec_and_lock.c44
-rw-r--r--include/asm-generic/qspinlock_types.h2
-rw-r--r--include/linux/refcount.h4
-rw-r--r--include/linux/spinlock.h5
-rw-r--r--kernel/locking/lockdep.c12
-rw-r--r--kernel/locking/rwsem.c1
-rw-r--r--lib/Makefile6
-rw-r--r--lib/dec_and_lock.c16
-rw-r--r--lib/refcount.c28
11 files changed, 61 insertions, 64 deletions
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 0c4805a572c8..04a4a138ed13 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -555,11 +555,6 @@ config SMP
555 555
556 If you don't know what to do here, say N. 556 If you don't know what to do here, say N.
557 557
558config HAVE_DEC_LOCK
559 bool
560 depends on SMP
561 default y
562
563config NR_CPUS 558config NR_CPUS
564 int "Maximum number of CPUs (2-32)" 559 int "Maximum number of CPUs (2-32)"
565 range 2 32 560 range 2 32
diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile
index 04f9729de57c..854d5e79979e 100644
--- a/arch/alpha/lib/Makefile
+++ b/arch/alpha/lib/Makefile
@@ -35,8 +35,6 @@ lib-y = __divqu.o __remqu.o __divlu.o __remlu.o \
35 callback_srm.o srm_puts.o srm_printk.o \ 35 callback_srm.o srm_puts.o srm_printk.o \
36 fls.o 36 fls.o
37 37
38lib-$(CONFIG_SMP) += dec_and_lock.o
39
40# The division routines are built from single source, with different defines. 38# The division routines are built from single source, with different defines.
41AFLAGS___divqu.o = -DDIV 39AFLAGS___divqu.o = -DDIV
42AFLAGS___remqu.o = -DREM 40AFLAGS___remqu.o = -DREM
diff --git a/arch/alpha/lib/dec_and_lock.c b/arch/alpha/lib/dec_and_lock.c
deleted file mode 100644
index a117707f57fe..000000000000
--- a/arch/alpha/lib/dec_and_lock.c
+++ /dev/null
@@ -1,44 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * arch/alpha/lib/dec_and_lock.c
4 *
5 * ll/sc version of atomic_dec_and_lock()
6 *
7 */
8
9#include <linux/spinlock.h>
10#include <linux/atomic.h>
11#include <linux/export.h>
12
13 asm (".text \n\
14 .global _atomic_dec_and_lock \n\
15 .ent _atomic_dec_and_lock \n\
16 .align 4 \n\
17_atomic_dec_and_lock: \n\
18 .prologue 0 \n\
191: ldl_l $1, 0($16) \n\
20 subl $1, 1, $1 \n\
21 beq $1, 2f \n\
22 stl_c $1, 0($16) \n\
23 beq $1, 4f \n\
24 mb \n\
25 clr $0 \n\
26 ret \n\
272: br $29, 3f \n\
283: ldgp $29, 0($29) \n\
29 br $atomic_dec_and_lock_1..ng \n\
30 .subsection 2 \n\
314: br 1b \n\
32 .previous \n\
33 .end _atomic_dec_and_lock");
34
35static int __used atomic_dec_and_lock_1(atomic_t *atomic, spinlock_t *lock)
36{
37 /* Slow path */
38 spin_lock(lock);
39 if (atomic_dec_and_test(atomic))
40 return 1;
41 spin_unlock(lock);
42 return 0;
43}
44EXPORT_SYMBOL(_atomic_dec_and_lock);
diff --git a/include/asm-generic/qspinlock_types.h b/include/asm-generic/qspinlock_types.h
index 0763f065b975..d10f1e7d6ba8 100644
--- a/include/asm-generic/qspinlock_types.h
+++ b/include/asm-generic/qspinlock_types.h
@@ -63,7 +63,7 @@ typedef struct qspinlock {
63/* 63/*
64 * Initializier 64 * Initializier
65 */ 65 */
66#define __ARCH_SPIN_LOCK_UNLOCKED { .val = ATOMIC_INIT(0) } 66#define __ARCH_SPIN_LOCK_UNLOCKED { { .val = ATOMIC_INIT(0) } }
67 67
68/* 68/*
69 * Bitfields in the atomic value: 69 * Bitfields in the atomic value:
diff --git a/include/linux/refcount.h b/include/linux/refcount.h
index 4193c41e383a..a685da2c4522 100644
--- a/include/linux/refcount.h
+++ b/include/linux/refcount.h
@@ -98,5 +98,7 @@ extern __must_check bool refcount_dec_if_one(refcount_t *r);
98extern __must_check bool refcount_dec_not_one(refcount_t *r); 98extern __must_check bool refcount_dec_not_one(refcount_t *r);
99extern __must_check bool refcount_dec_and_mutex_lock(refcount_t *r, struct mutex *lock); 99extern __must_check bool refcount_dec_and_mutex_lock(refcount_t *r, struct mutex *lock);
100extern __must_check bool refcount_dec_and_lock(refcount_t *r, spinlock_t *lock); 100extern __must_check bool refcount_dec_and_lock(refcount_t *r, spinlock_t *lock);
101 101extern __must_check bool refcount_dec_and_lock_irqsave(refcount_t *r,
102 spinlock_t *lock,
103 unsigned long *flags);
102#endif /* _LINUX_REFCOUNT_H */ 104#endif /* _LINUX_REFCOUNT_H */
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index 1e8a46435838..fd57888d4942 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -427,6 +427,11 @@ extern int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock);
427#define atomic_dec_and_lock(atomic, lock) \ 427#define atomic_dec_and_lock(atomic, lock) \
428 __cond_lock(lock, _atomic_dec_and_lock(atomic, lock)) 428 __cond_lock(lock, _atomic_dec_and_lock(atomic, lock))
429 429
430extern int _atomic_dec_and_lock_irqsave(atomic_t *atomic, spinlock_t *lock,
431 unsigned long *flags);
432#define atomic_dec_and_lock_irqsave(atomic, lock, flags) \
433 __cond_lock(lock, _atomic_dec_and_lock_irqsave(atomic, lock, &(flags)))
434
430int alloc_bucket_spinlocks(spinlock_t **locks, unsigned int *lock_mask, 435int alloc_bucket_spinlocks(spinlock_t **locks, unsigned int *lock_mask,
431 size_t max_size, unsigned int cpu_mult, 436 size_t max_size, unsigned int cpu_mult,
432 gfp_t gfp); 437 gfp_t gfp);
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index edcac5de7ebc..5fa4d3138bf1 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -1265,11 +1265,11 @@ unsigned long lockdep_count_forward_deps(struct lock_class *class)
1265 this.parent = NULL; 1265 this.parent = NULL;
1266 this.class = class; 1266 this.class = class;
1267 1267
1268 local_irq_save(flags); 1268 raw_local_irq_save(flags);
1269 arch_spin_lock(&lockdep_lock); 1269 arch_spin_lock(&lockdep_lock);
1270 ret = __lockdep_count_forward_deps(&this); 1270 ret = __lockdep_count_forward_deps(&this);
1271 arch_spin_unlock(&lockdep_lock); 1271 arch_spin_unlock(&lockdep_lock);
1272 local_irq_restore(flags); 1272 raw_local_irq_restore(flags);
1273 1273
1274 return ret; 1274 return ret;
1275} 1275}
@@ -1292,11 +1292,11 @@ unsigned long lockdep_count_backward_deps(struct lock_class *class)
1292 this.parent = NULL; 1292 this.parent = NULL;
1293 this.class = class; 1293 this.class = class;
1294 1294
1295 local_irq_save(flags); 1295 raw_local_irq_save(flags);
1296 arch_spin_lock(&lockdep_lock); 1296 arch_spin_lock(&lockdep_lock);
1297 ret = __lockdep_count_backward_deps(&this); 1297 ret = __lockdep_count_backward_deps(&this);
1298 arch_spin_unlock(&lockdep_lock); 1298 arch_spin_unlock(&lockdep_lock);
1299 local_irq_restore(flags); 1299 raw_local_irq_restore(flags);
1300 1300
1301 return ret; 1301 return ret;
1302} 1302}
@@ -4411,7 +4411,7 @@ void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len)
4411 if (unlikely(!debug_locks)) 4411 if (unlikely(!debug_locks))
4412 return; 4412 return;
4413 4413
4414 local_irq_save(flags); 4414 raw_local_irq_save(flags);
4415 for (i = 0; i < curr->lockdep_depth; i++) { 4415 for (i = 0; i < curr->lockdep_depth; i++) {
4416 hlock = curr->held_locks + i; 4416 hlock = curr->held_locks + i;
4417 4417
@@ -4422,7 +4422,7 @@ void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len)
4422 print_freed_lock_bug(curr, mem_from, mem_from + mem_len, hlock); 4422 print_freed_lock_bug(curr, mem_from, mem_from + mem_len, hlock);
4423 break; 4423 break;
4424 } 4424 }
4425 local_irq_restore(flags); 4425 raw_local_irq_restore(flags);
4426} 4426}
4427EXPORT_SYMBOL_GPL(debug_check_no_locks_freed); 4427EXPORT_SYMBOL_GPL(debug_check_no_locks_freed);
4428 4428
diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c
index bc1e507be9ff..776308d2fa9e 100644
--- a/kernel/locking/rwsem.c
+++ b/kernel/locking/rwsem.c
@@ -181,6 +181,7 @@ void down_read_non_owner(struct rw_semaphore *sem)
181 might_sleep(); 181 might_sleep();
182 182
183 __down_read(sem); 183 __down_read(sem);
184 rwsem_set_reader_owned(sem);
184} 185}
185 186
186EXPORT_SYMBOL(down_read_non_owner); 187EXPORT_SYMBOL(down_read_non_owner);
diff --git a/lib/Makefile b/lib/Makefile
index 8153fdab287f..90dc5520b784 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -23,7 +23,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
23 sha1.o chacha20.o irq_regs.o argv_split.o \ 23 sha1.o chacha20.o irq_regs.o argv_split.o \
24 flex_proportions.o ratelimit.o show_mem.o \ 24 flex_proportions.o ratelimit.o show_mem.o \
25 is_single_threaded.o plist.o decompress.o kobject_uevent.o \ 25 is_single_threaded.o plist.o decompress.o kobject_uevent.o \
26 earlycpio.o seq_buf.o siphash.o \ 26 earlycpio.o seq_buf.o siphash.o dec_and_lock.o \
27 nmi_backtrace.o nodemask.o win_minmax.o 27 nmi_backtrace.o nodemask.o win_minmax.o
28 28
29lib-$(CONFIG_PRINTK) += dump_stack.o 29lib-$(CONFIG_PRINTK) += dump_stack.o
@@ -95,10 +95,6 @@ obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
95obj-$(CONFIG_DEBUG_LIST) += list_debug.o 95obj-$(CONFIG_DEBUG_LIST) += list_debug.o
96obj-$(CONFIG_DEBUG_OBJECTS) += debugobjects.o 96obj-$(CONFIG_DEBUG_OBJECTS) += debugobjects.o
97 97
98ifneq ($(CONFIG_HAVE_DEC_LOCK),y)
99 lib-y += dec_and_lock.o
100endif
101
102obj-$(CONFIG_BITREVERSE) += bitrev.o 98obj-$(CONFIG_BITREVERSE) += bitrev.o
103obj-$(CONFIG_RATIONAL) += rational.o 99obj-$(CONFIG_RATIONAL) += rational.o
104obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o 100obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o
diff --git a/lib/dec_and_lock.c b/lib/dec_and_lock.c
index 347fa7ac2e8a..9555b68bb774 100644
--- a/lib/dec_and_lock.c
+++ b/lib/dec_and_lock.c
@@ -33,3 +33,19 @@ int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
33} 33}
34 34
35EXPORT_SYMBOL(_atomic_dec_and_lock); 35EXPORT_SYMBOL(_atomic_dec_and_lock);
36
37int _atomic_dec_and_lock_irqsave(atomic_t *atomic, spinlock_t *lock,
38 unsigned long *flags)
39{
40 /* Subtract 1 from counter unless that drops it to 0 (ie. it was 1) */
41 if (atomic_add_unless(atomic, -1, 1))
42 return 0;
43
44 /* Otherwise do it the slow way */
45 spin_lock_irqsave(lock, *flags);
46 if (atomic_dec_and_test(atomic))
47 return 1;
48 spin_unlock_irqrestore(lock, *flags);
49 return 0;
50}
51EXPORT_SYMBOL(_atomic_dec_and_lock_irqsave);
diff --git a/lib/refcount.c b/lib/refcount.c
index 0eb48353abe3..d3b81cefce91 100644
--- a/lib/refcount.c
+++ b/lib/refcount.c
@@ -350,3 +350,31 @@ bool refcount_dec_and_lock(refcount_t *r, spinlock_t *lock)
350} 350}
351EXPORT_SYMBOL(refcount_dec_and_lock); 351EXPORT_SYMBOL(refcount_dec_and_lock);
352 352
353/**
354 * refcount_dec_and_lock_irqsave - return holding spinlock with disabled
355 * interrupts if able to decrement refcount to 0
356 * @r: the refcount
357 * @lock: the spinlock to be locked
358 * @flags: saved IRQ-flags if the is acquired
359 *
360 * Same as refcount_dec_and_lock() above except that the spinlock is acquired
361 * with disabled interupts.
362 *
363 * Return: true and hold spinlock if able to decrement refcount to 0, false
364 * otherwise
365 */
366bool refcount_dec_and_lock_irqsave(refcount_t *r, spinlock_t *lock,
367 unsigned long *flags)
368{
369 if (refcount_dec_not_one(r))
370 return false;
371
372 spin_lock_irqsave(lock, *flags);
373 if (!refcount_dec_and_test(r)) {
374 spin_unlock_irqrestore(lock, *flags);
375 return false;
376 }
377
378 return true;
379}
380EXPORT_SYMBOL(refcount_dec_and_lock_irqsave);