aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWaiman Long <longman@redhat.com>2019-03-22 10:30:07 -0400
committerIngo Molnar <mingo@kernel.org>2019-04-03 08:50:52 -0400
commit390a0c62c23cb026cd4664a66f6f45fed3a215f6 (patch)
tree4c165e3312c28313f0e83bac3121c09559bd73fd
parent46ad0840b1584b92b5ff2cc3ed0b011dd6b8e0f1 (diff)
locking/rwsem: Remove rwsem-spinlock.c & use rwsem-xadd.c for all archs
Currently, we have two different implementation of rwsem: 1) CONFIG_RWSEM_GENERIC_SPINLOCK (rwsem-spinlock.c) 2) CONFIG_RWSEM_XCHGADD_ALGORITHM (rwsem-xadd.c) As we are going to use a single generic implementation for rwsem-xadd.c and no architecture-specific code will be needed, there is no point in keeping two different implementations of rwsem. In most cases, the performance of rwsem-spinlock.c will be worse. It also doesn't get all the performance tuning and optimizations that had been implemented in rwsem-xadd.c over the years. For simplication, we are going to remove rwsem-spinlock.c and make all architectures use a single implementation of rwsem - rwsem-xadd.c. All references to RWSEM_GENERIC_SPINLOCK and RWSEM_XCHGADD_ALGORITHM in the code are removed. Suggested-by: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Waiman Long <longman@redhat.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Linus Torvalds <torvalds@linux-foundation.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Borislav Petkov <bp@alien8.de> Cc: Davidlohr Bueso <dave@stgolabs.net> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Tim Chen <tim.c.chen@linux.intel.com> Cc: Will Deacon <will.deacon@arm.com> Cc: linux-arm-kernel@lists.infradead.org Cc: linux-c6x-dev@linux-c6x.org Cc: linux-m68k@lists.linux-m68k.org Cc: linux-riscv@lists.infradead.org Cc: linux-um@lists.infradead.org Cc: linux-xtensa@linux-xtensa.org Cc: linuxppc-dev@lists.ozlabs.org Cc: nios2-dev@lists.rocketboards.org Cc: openrisc@lists.librecores.org Cc: uclinux-h8-devel@lists.sourceforge.jp Link: https://lkml.kernel.org/r/20190322143008.21313-3-longman@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/alpha/Kconfig7
-rw-r--r--arch/arc/Kconfig3
-rw-r--r--arch/arm/Kconfig4
-rw-r--r--arch/arm64/Kconfig3
-rw-r--r--arch/c6x/Kconfig3
-rw-r--r--arch/csky/Kconfig3
-rw-r--r--arch/h8300/Kconfig3
-rw-r--r--arch/hexagon/Kconfig6
-rw-r--r--arch/ia64/Kconfig4
-rw-r--r--arch/m68k/Kconfig7
-rw-r--r--arch/microblaze/Kconfig6
-rw-r--r--arch/mips/Kconfig7
-rw-r--r--arch/nds32/Kconfig3
-rw-r--r--arch/nios2/Kconfig3
-rw-r--r--arch/openrisc/Kconfig6
-rw-r--r--arch/parisc/Kconfig6
-rw-r--r--arch/powerpc/Kconfig7
-rw-r--r--arch/riscv/Kconfig3
-rw-r--r--arch/s390/Kconfig6
-rw-r--r--arch/sh/Kconfig6
-rw-r--r--arch/sparc/Kconfig8
-rw-r--r--arch/unicore32/Kconfig6
-rw-r--r--arch/x86/Kconfig3
-rw-r--r--arch/x86/um/Kconfig6
-rw-r--r--arch/xtensa/Kconfig3
-rw-r--r--include/linux/rwsem-spinlock.h47
-rw-r--r--include/linux/rwsem.h5
-rw-r--r--kernel/Kconfig.locks2
-rw-r--r--kernel/locking/Makefile4
-rw-r--r--kernel/locking/rwsem-spinlock.c339
-rw-r--r--kernel/locking/rwsem.h3
31 files changed, 2 insertions, 520 deletions
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 584a6e114853..27c871227eee 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -49,13 +49,6 @@ config MMU
49 bool 49 bool
50 default y 50 default y
51 51
52config RWSEM_GENERIC_SPINLOCK
53 bool
54
55config RWSEM_XCHGADD_ALGORITHM
56 bool
57 default y
58
59config ARCH_HAS_ILOG2_U32 52config ARCH_HAS_ILOG2_U32
60 bool 53 bool
61 default n 54 default n
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index c781e45d1d99..23e063df5d2c 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -63,9 +63,6 @@ config SCHED_OMIT_FRAME_POINTER
63config GENERIC_CSUM 63config GENERIC_CSUM
64 def_bool y 64 def_bool y
65 65
66config RWSEM_GENERIC_SPINLOCK
67 def_bool y
68
69config ARCH_DISCONTIGMEM_ENABLE 66config ARCH_DISCONTIGMEM_ENABLE
70 def_bool n 67 def_bool n
71 68
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 850b4805e2d1..c8b03e1c6c2a 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -178,10 +178,6 @@ config TRACE_IRQFLAGS_SUPPORT
178 bool 178 bool
179 default !CPU_V7M 179 default !CPU_V7M
180 180
181config RWSEM_XCHGADD_ALGORITHM
182 bool
183 default y
184
185config ARCH_HAS_ILOG2_U32 181config ARCH_HAS_ILOG2_U32
186 bool 182 bool
187 183
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 7e34b9eba5de..c62b9db2b5e8 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -237,9 +237,6 @@ config LOCKDEP_SUPPORT
237config TRACE_IRQFLAGS_SUPPORT 237config TRACE_IRQFLAGS_SUPPORT
238 def_bool y 238 def_bool y
239 239
240config RWSEM_XCHGADD_ALGORITHM
241 def_bool y
242
243config GENERIC_BUG 240config GENERIC_BUG
244 def_bool y 241 def_bool y
245 depends on BUG 242 depends on BUG
diff --git a/arch/c6x/Kconfig b/arch/c6x/Kconfig
index e5cd3c5f8399..ed92b5840c0a 100644
--- a/arch/c6x/Kconfig
+++ b/arch/c6x/Kconfig
@@ -27,9 +27,6 @@ config MMU
27config FPU 27config FPU
28 def_bool n 28 def_bool n
29 29
30config RWSEM_GENERIC_SPINLOCK
31 def_bool y
32
33config GENERIC_CALIBRATE_DELAY 30config GENERIC_CALIBRATE_DELAY
34 def_bool y 31 def_bool y
35 32
diff --git a/arch/csky/Kconfig b/arch/csky/Kconfig
index 725a115759c9..6555d1781132 100644
--- a/arch/csky/Kconfig
+++ b/arch/csky/Kconfig
@@ -92,9 +92,6 @@ config GENERIC_HWEIGHT
92config MMU 92config MMU
93 def_bool y 93 def_bool y
94 94
95config RWSEM_GENERIC_SPINLOCK
96 def_bool y
97
98config STACKTRACE_SUPPORT 95config STACKTRACE_SUPPORT
99 def_bool y 96 def_bool y
100 97
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index c071da34e081..61c01db6c292 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -27,9 +27,6 @@ config H8300
27config CPU_BIG_ENDIAN 27config CPU_BIG_ENDIAN
28 def_bool y 28 def_bool y
29 29
30config RWSEM_GENERIC_SPINLOCK
31 def_bool y
32
33config GENERIC_HWEIGHT 30config GENERIC_HWEIGHT
34 def_bool y 31 def_bool y
35 32
diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig
index ac441680dcc0..3e54a53208d5 100644
--- a/arch/hexagon/Kconfig
+++ b/arch/hexagon/Kconfig
@@ -65,12 +65,6 @@ config GENERIC_CSUM
65config GENERIC_IRQ_PROBE 65config GENERIC_IRQ_PROBE
66 def_bool y 66 def_bool y
67 67
68config RWSEM_GENERIC_SPINLOCK
69 def_bool n
70
71config RWSEM_XCHGADD_ALGORITHM
72 def_bool y
73
74config GENERIC_HWEIGHT 68config GENERIC_HWEIGHT
75 def_bool y 69 def_bool y
76 70
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 8d7396bd1790..73a26f04644e 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -83,10 +83,6 @@ config STACKTRACE_SUPPORT
83config GENERIC_LOCKBREAK 83config GENERIC_LOCKBREAK
84 def_bool n 84 def_bool n
85 85
86config RWSEM_XCHGADD_ALGORITHM
87 bool
88 default y
89
90config HUGETLB_PAGE_SIZE_VARIABLE 86config HUGETLB_PAGE_SIZE_VARIABLE
91 bool 87 bool
92 depends on HUGETLB_PAGE 88 depends on HUGETLB_PAGE
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index b54206408f91..f5661f48019c 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -32,13 +32,6 @@ config M68K
32config CPU_BIG_ENDIAN 32config CPU_BIG_ENDIAN
33 def_bool y 33 def_bool y
34 34
35config RWSEM_GENERIC_SPINLOCK
36 bool
37 default y
38
39config RWSEM_XCHGADD_ALGORITHM
40 bool
41
42config ARCH_HAS_ILOG2_U32 35config ARCH_HAS_ILOG2_U32
43 bool 36 bool
44 37
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index a51b965b3b82..a7a9a9d59f65 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -58,15 +58,9 @@ config CPU_LITTLE_ENDIAN
58 58
59endchoice 59endchoice
60 60
61config RWSEM_GENERIC_SPINLOCK
62 def_bool y
63
64config ZONE_DMA 61config ZONE_DMA
65 def_bool y 62 def_bool y
66 63
67config RWSEM_XCHGADD_ALGORITHM
68 bool
69
70config ARCH_HAS_ILOG2_U32 64config ARCH_HAS_ILOG2_U32
71 def_bool n 65 def_bool n
72 66
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 4a5f5b0ee9a9..b9c48b27162d 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1037,13 +1037,6 @@ source "arch/mips/paravirt/Kconfig"
1037 1037
1038endmenu 1038endmenu
1039 1039
1040config RWSEM_GENERIC_SPINLOCK
1041 bool
1042 default y
1043
1044config RWSEM_XCHGADD_ALGORITHM
1045 bool
1046
1047config GENERIC_HWEIGHT 1040config GENERIC_HWEIGHT
1048 bool 1041 bool
1049 default y 1042 default y
diff --git a/arch/nds32/Kconfig b/arch/nds32/Kconfig
index addb7f5f5264..55559ca0efe4 100644
--- a/arch/nds32/Kconfig
+++ b/arch/nds32/Kconfig
@@ -60,9 +60,6 @@ config GENERIC_LOCKBREAK
60 def_bool y 60 def_bool y
61 depends on PREEMPT 61 depends on PREEMPT
62 62
63config RWSEM_GENERIC_SPINLOCK
64 def_bool y
65
66config TRACE_IRQFLAGS_SUPPORT 63config TRACE_IRQFLAGS_SUPPORT
67 def_bool y 64 def_bool y
68 65
diff --git a/arch/nios2/Kconfig b/arch/nios2/Kconfig
index 4ef15a61b7bc..56685fd45ed0 100644
--- a/arch/nios2/Kconfig
+++ b/arch/nios2/Kconfig
@@ -40,9 +40,6 @@ config NO_IOPORT_MAP
40config FPU 40config FPU
41 def_bool n 41 def_bool n
42 42
43config RWSEM_GENERIC_SPINLOCK
44 def_bool y
45
46config TRACE_IRQFLAGS_SUPPORT 43config TRACE_IRQFLAGS_SUPPORT
47 def_bool n 44 def_bool n
48 45
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
index a5e361fbb75a..683511b8c9df 100644
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -43,12 +43,6 @@ config CPU_BIG_ENDIAN
43config MMU 43config MMU
44 def_bool y 44 def_bool y
45 45
46config RWSEM_GENERIC_SPINLOCK
47 def_bool y
48
49config RWSEM_XCHGADD_ALGORITHM
50 def_bool n
51
52config GENERIC_HWEIGHT 46config GENERIC_HWEIGHT
53 def_bool y 47 def_bool y
54 48
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index c8e621296092..f1ed8ddfe486 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -75,12 +75,6 @@ config GENERIC_LOCKBREAK
75 default y 75 default y
76 depends on SMP && PREEMPT 76 depends on SMP && PREEMPT
77 77
78config RWSEM_GENERIC_SPINLOCK
79 def_bool y
80
81config RWSEM_XCHGADD_ALGORITHM
82 bool
83
84config ARCH_HAS_ILOG2_U32 78config ARCH_HAS_ILOG2_U32
85 bool 79 bool
86 default n 80 default n
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 2d0be82c3061..e5dd6aafaf68 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -103,13 +103,6 @@ config LOCKDEP_SUPPORT
103 bool 103 bool
104 default y 104 default y
105 105
106config RWSEM_GENERIC_SPINLOCK
107 bool
108
109config RWSEM_XCHGADD_ALGORITHM
110 bool
111 default y
112
113config GENERIC_LOCKBREAK 106config GENERIC_LOCKBREAK
114 bool 107 bool
115 default y 108 default y
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index eb56c82d8aa1..0582260fb6c2 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -69,9 +69,6 @@ config STACKTRACE_SUPPORT
69config TRACE_IRQFLAGS_SUPPORT 69config TRACE_IRQFLAGS_SUPPORT
70 def_bool y 70 def_bool y
71 71
72config RWSEM_GENERIC_SPINLOCK
73 def_bool y
74
75config GENERIC_BUG 72config GENERIC_BUG
76 def_bool y 73 def_bool y
77 depends on BUG 74 depends on BUG
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index b6e3d0653002..c9300b437195 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -14,12 +14,6 @@ config LOCKDEP_SUPPORT
14config STACKTRACE_SUPPORT 14config STACKTRACE_SUPPORT
15 def_bool y 15 def_bool y
16 16
17config RWSEM_GENERIC_SPINLOCK
18 bool
19
20config RWSEM_XCHGADD_ALGORITHM
21 def_bool y
22
23config ARCH_HAS_ILOG2_U32 17config ARCH_HAS_ILOG2_U32
24 def_bool n 18 def_bool n
25 19
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index b1c91ea9a958..0be08d586d40 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -90,12 +90,6 @@ config ARCH_DEFCONFIG
90 default "arch/sh/configs/shx3_defconfig" if SUPERH32 90 default "arch/sh/configs/shx3_defconfig" if SUPERH32
91 default "arch/sh/configs/cayman_defconfig" if SUPERH64 91 default "arch/sh/configs/cayman_defconfig" if SUPERH64
92 92
93config RWSEM_GENERIC_SPINLOCK
94 def_bool y
95
96config RWSEM_XCHGADD_ALGORITHM
97 bool
98
99config GENERIC_BUG 93config GENERIC_BUG
100 def_bool y 94 def_bool y
101 depends on BUG && SUPERH32 95 depends on BUG && SUPERH32
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 40f8f4f73fe8..16b620237816 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -191,14 +191,6 @@ config NR_CPUS
191 191
192source "kernel/Kconfig.hz" 192source "kernel/Kconfig.hz"
193 193
194config RWSEM_GENERIC_SPINLOCK
195 bool
196 default y if SPARC32
197
198config RWSEM_XCHGADD_ALGORITHM
199 bool
200 default y if SPARC64
201
202config GENERIC_HWEIGHT 194config GENERIC_HWEIGHT
203 bool 195 bool
204 default y 196 default y
diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig
index 817d82608712..0d5869c9bf03 100644
--- a/arch/unicore32/Kconfig
+++ b/arch/unicore32/Kconfig
@@ -38,12 +38,6 @@ config STACKTRACE_SUPPORT
38config LOCKDEP_SUPPORT 38config LOCKDEP_SUPPORT
39 def_bool y 39 def_bool y
40 40
41config RWSEM_GENERIC_SPINLOCK
42 def_bool y
43
44config RWSEM_XCHGADD_ALGORITHM
45 bool
46
47config ARCH_HAS_ILOG2_U32 41config ARCH_HAS_ILOG2_U32
48 bool 42 bool
49 43
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 5ad92419be19..84b184e016cd 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -268,9 +268,6 @@ config ARCH_MAY_HAVE_PC_FDC
268 def_bool y 268 def_bool y
269 depends on ISA_DMA_API 269 depends on ISA_DMA_API
270 270
271config RWSEM_XCHGADD_ALGORITHM
272 def_bool y
273
274config GENERIC_CALIBRATE_DELAY 271config GENERIC_CALIBRATE_DELAY
275 def_bool y 272 def_bool y
276 273
diff --git a/arch/x86/um/Kconfig b/arch/x86/um/Kconfig
index a9e80e44178c..a8985e1f7432 100644
--- a/arch/x86/um/Kconfig
+++ b/arch/x86/um/Kconfig
@@ -32,12 +32,6 @@ config ARCH_DEFCONFIG
32 default "arch/um/configs/i386_defconfig" if X86_32 32 default "arch/um/configs/i386_defconfig" if X86_32
33 default "arch/um/configs/x86_64_defconfig" if X86_64 33 default "arch/um/configs/x86_64_defconfig" if X86_64
34 34
35config RWSEM_XCHGADD_ALGORITHM
36 def_bool 64BIT
37
38config RWSEM_GENERIC_SPINLOCK
39 def_bool !RWSEM_XCHGADD_ALGORITHM
40
41config 3_LEVEL_PGTABLES 35config 3_LEVEL_PGTABLES
42 bool "Three-level pagetables" if !64BIT 36 bool "Three-level pagetables" if !64BIT
43 default 64BIT 37 default 64BIT
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 4b9aafe766c5..35c8d91e6106 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -46,9 +46,6 @@ config XTENSA
46 with reasonable minimum requirements. The Xtensa Linux project has 46 with reasonable minimum requirements. The Xtensa Linux project has
47 a home page at <http://www.linux-xtensa.org/>. 47 a home page at <http://www.linux-xtensa.org/>.
48 48
49config RWSEM_XCHGADD_ALGORITHM
50 def_bool y
51
52config GENERIC_HWEIGHT 49config GENERIC_HWEIGHT
53 def_bool y 50 def_bool y
54 51
diff --git a/include/linux/rwsem-spinlock.h b/include/linux/rwsem-spinlock.h
deleted file mode 100644
index e47568363e5e..000000000000
--- a/include/linux/rwsem-spinlock.h
+++ /dev/null
@@ -1,47 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/* rwsem-spinlock.h: fallback C implementation
3 *
4 * Copyright (c) 2001 David Howells (dhowells@redhat.com).
5 * - Derived partially from ideas by Andrea Arcangeli <andrea@suse.de>
6 * - Derived also from comments by Linus
7 */
8
9#ifndef _LINUX_RWSEM_SPINLOCK_H
10#define _LINUX_RWSEM_SPINLOCK_H
11
12#ifndef _LINUX_RWSEM_H
13#error "please don't include linux/rwsem-spinlock.h directly, use linux/rwsem.h instead"
14#endif
15
16#ifdef __KERNEL__
17/*
18 * the rw-semaphore definition
19 * - if count is 0 then there are no active readers or writers
20 * - if count is +ve then that is the number of active readers
21 * - if count is -1 then there is one active writer
22 * - if wait_list is not empty, then there are processes waiting for the semaphore
23 */
24struct rw_semaphore {
25 __s32 count;
26 raw_spinlock_t wait_lock;
27 struct list_head wait_list;
28#ifdef CONFIG_DEBUG_LOCK_ALLOC
29 struct lockdep_map dep_map;
30#endif
31};
32
33#define RWSEM_UNLOCKED_VALUE 0x00000000
34
35extern void __down_read(struct rw_semaphore *sem);
36extern int __must_check __down_read_killable(struct rw_semaphore *sem);
37extern int __down_read_trylock(struct rw_semaphore *sem);
38extern void __down_write(struct rw_semaphore *sem);
39extern int __must_check __down_write_killable(struct rw_semaphore *sem);
40extern int __down_write_trylock(struct rw_semaphore *sem);
41extern void __up_read(struct rw_semaphore *sem);
42extern void __up_write(struct rw_semaphore *sem);
43extern void __downgrade_write(struct rw_semaphore *sem);
44extern int rwsem_is_locked(struct rw_semaphore *sem);
45
46#endif /* __KERNEL__ */
47#endif /* _LINUX_RWSEM_SPINLOCK_H */
diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h
index 6e56006b2cb6..0fc41062c649 100644
--- a/include/linux/rwsem.h
+++ b/include/linux/rwsem.h
@@ -22,10 +22,6 @@
22 22
23struct rw_semaphore; 23struct rw_semaphore;
24 24
25#ifdef CONFIG_RWSEM_GENERIC_SPINLOCK
26#include <linux/rwsem-spinlock.h> /* use a generic implementation */
27#define __RWSEM_INIT_COUNT(name) .count = RWSEM_UNLOCKED_VALUE
28#else
29/* All arch specific implementations share the same struct */ 25/* All arch specific implementations share the same struct */
30struct rw_semaphore { 26struct rw_semaphore {
31 atomic_long_t count; 27 atomic_long_t count;
@@ -65,7 +61,6 @@ static inline int rwsem_is_locked(struct rw_semaphore *sem)
65 61
66#define RWSEM_UNLOCKED_VALUE 0L 62#define RWSEM_UNLOCKED_VALUE 0L
67#define __RWSEM_INIT_COUNT(name) .count = ATOMIC_LONG_INIT(RWSEM_UNLOCKED_VALUE) 63#define __RWSEM_INIT_COUNT(name) .count = ATOMIC_LONG_INIT(RWSEM_UNLOCKED_VALUE)
68#endif
69 64
70/* Common initializer macros and functions */ 65/* Common initializer macros and functions */
71 66
diff --git a/kernel/Kconfig.locks b/kernel/Kconfig.locks
index fbba478ae522..e335953fa704 100644
--- a/kernel/Kconfig.locks
+++ b/kernel/Kconfig.locks
@@ -229,7 +229,7 @@ config MUTEX_SPIN_ON_OWNER
229 229
230config RWSEM_SPIN_ON_OWNER 230config RWSEM_SPIN_ON_OWNER
231 def_bool y 231 def_bool y
232 depends on SMP && RWSEM_XCHGADD_ALGORITHM && ARCH_SUPPORTS_ATOMIC_RMW 232 depends on SMP && ARCH_SUPPORTS_ATOMIC_RMW
233 233
234config LOCK_SPIN_ON_OWNER 234config LOCK_SPIN_ON_OWNER
235 def_bool y 235 def_bool y
diff --git a/kernel/locking/Makefile b/kernel/locking/Makefile
index 392c7f23af76..1af83e9ce57d 100644
--- a/kernel/locking/Makefile
+++ b/kernel/locking/Makefile
@@ -3,7 +3,7 @@
3# and is generally not a function of system call inputs. 3# and is generally not a function of system call inputs.
4KCOV_INSTRUMENT := n 4KCOV_INSTRUMENT := n
5 5
6obj-y += mutex.o semaphore.o rwsem.o percpu-rwsem.o 6obj-y += mutex.o semaphore.o rwsem.o percpu-rwsem.o rwsem-xadd.o
7 7
8ifdef CONFIG_FUNCTION_TRACER 8ifdef CONFIG_FUNCTION_TRACER
9CFLAGS_REMOVE_lockdep.o = $(CC_FLAGS_FTRACE) 9CFLAGS_REMOVE_lockdep.o = $(CC_FLAGS_FTRACE)
@@ -25,8 +25,6 @@ obj-$(CONFIG_RT_MUTEXES) += rtmutex.o
25obj-$(CONFIG_DEBUG_RT_MUTEXES) += rtmutex-debug.o 25obj-$(CONFIG_DEBUG_RT_MUTEXES) += rtmutex-debug.o
26obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o 26obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o
27obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o 27obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
28obj-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
29obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem-xadd.o
30obj-$(CONFIG_QUEUED_RWLOCKS) += qrwlock.o 28obj-$(CONFIG_QUEUED_RWLOCKS) += qrwlock.o
31obj-$(CONFIG_LOCK_TORTURE_TEST) += locktorture.o 29obj-$(CONFIG_LOCK_TORTURE_TEST) += locktorture.o
32obj-$(CONFIG_WW_MUTEX_SELFTEST) += test-ww_mutex.o 30obj-$(CONFIG_WW_MUTEX_SELFTEST) += test-ww_mutex.o
diff --git a/kernel/locking/rwsem-spinlock.c b/kernel/locking/rwsem-spinlock.c
deleted file mode 100644
index a7ffb2a96ede..000000000000
--- a/kernel/locking/rwsem-spinlock.c
+++ /dev/null
@@ -1,339 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0
2/* rwsem-spinlock.c: R/W semaphores: contention handling functions for
3 * generic spinlock implementation
4 *
5 * Copyright (c) 2001 David Howells (dhowells@redhat.com).
6 * - Derived partially from idea by Andrea Arcangeli <andrea@suse.de>
7 * - Derived also from comments by Linus
8 */
9#include <linux/rwsem.h>
10#include <linux/sched/signal.h>
11#include <linux/sched/debug.h>
12#include <linux/export.h>
13
14enum rwsem_waiter_type {
15 RWSEM_WAITING_FOR_WRITE,
16 RWSEM_WAITING_FOR_READ
17};
18
19struct rwsem_waiter {
20 struct list_head list;
21 struct task_struct *task;
22 enum rwsem_waiter_type type;
23};
24
25int rwsem_is_locked(struct rw_semaphore *sem)
26{
27 int ret = 1;
28 unsigned long flags;
29
30 if (raw_spin_trylock_irqsave(&sem->wait_lock, flags)) {
31 ret = (sem->count != 0);
32 raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
33 }
34 return ret;
35}
36EXPORT_SYMBOL(rwsem_is_locked);
37
38/*
39 * initialise the semaphore
40 */
41void __init_rwsem(struct rw_semaphore *sem, const char *name,
42 struct lock_class_key *key)
43{
44#ifdef CONFIG_DEBUG_LOCK_ALLOC
45 /*
46 * Make sure we are not reinitializing a held semaphore:
47 */
48 debug_check_no_locks_freed((void *)sem, sizeof(*sem));
49 lockdep_init_map(&sem->dep_map, name, key, 0);
50#endif
51 sem->count = 0;
52 raw_spin_lock_init(&sem->wait_lock);
53 INIT_LIST_HEAD(&sem->wait_list);
54}
55EXPORT_SYMBOL(__init_rwsem);
56
57/*
58 * handle the lock release when processes blocked on it that can now run
59 * - if we come here, then:
60 * - the 'active count' _reached_ zero
61 * - the 'waiting count' is non-zero
62 * - the spinlock must be held by the caller
63 * - woken process blocks are discarded from the list after having task zeroed
64 * - writers are only woken if wakewrite is non-zero
65 */
66static inline struct rw_semaphore *
67__rwsem_do_wake(struct rw_semaphore *sem, int wakewrite)
68{
69 struct rwsem_waiter *waiter;
70 struct task_struct *tsk;
71 int woken;
72
73 waiter = list_entry(sem->wait_list.next, struct rwsem_waiter, list);
74
75 if (waiter->type == RWSEM_WAITING_FOR_WRITE) {
76 if (wakewrite)
77 /* Wake up a writer. Note that we do not grant it the
78 * lock - it will have to acquire it when it runs. */
79 wake_up_process(waiter->task);
80 goto out;
81 }
82
83 /* grant an infinite number of read locks to the front of the queue */
84 woken = 0;
85 do {
86 struct list_head *next = waiter->list.next;
87
88 list_del(&waiter->list);
89 tsk = waiter->task;
90 /*
91 * Make sure we do not wakeup the next reader before
92 * setting the nil condition to grant the next reader;
93 * otherwise we could miss the wakeup on the other
94 * side and end up sleeping again. See the pairing
95 * in rwsem_down_read_failed().
96 */
97 smp_mb();
98 waiter->task = NULL;
99 wake_up_process(tsk);
100 put_task_struct(tsk);
101 woken++;
102 if (next == &sem->wait_list)
103 break;
104 waiter = list_entry(next, struct rwsem_waiter, list);
105 } while (waiter->type != RWSEM_WAITING_FOR_WRITE);
106
107 sem->count += woken;
108
109 out:
110 return sem;
111}
112
113/*
114 * wake a single writer
115 */
116static inline struct rw_semaphore *
117__rwsem_wake_one_writer(struct rw_semaphore *sem)
118{
119 struct rwsem_waiter *waiter;
120
121 waiter = list_entry(sem->wait_list.next, struct rwsem_waiter, list);
122 wake_up_process(waiter->task);
123
124 return sem;
125}
126
127/*
128 * get a read lock on the semaphore
129 */
130int __sched __down_read_common(struct rw_semaphore *sem, int state)
131{
132 struct rwsem_waiter waiter;
133 unsigned long flags;
134
135 raw_spin_lock_irqsave(&sem->wait_lock, flags);
136
137 if (sem->count >= 0 && list_empty(&sem->wait_list)) {
138 /* granted */
139 sem->count++;
140 raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
141 goto out;
142 }
143
144 /* set up my own style of waitqueue */
145 waiter.task = current;
146 waiter.type = RWSEM_WAITING_FOR_READ;
147 get_task_struct(current);
148
149 list_add_tail(&waiter.list, &sem->wait_list);
150
151 /* wait to be given the lock */
152 for (;;) {
153 if (!waiter.task)
154 break;
155 if (signal_pending_state(state, current))
156 goto out_nolock;
157 set_current_state(state);
158 raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
159 schedule();
160 raw_spin_lock_irqsave(&sem->wait_lock, flags);
161 }
162
163 raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
164 out:
165 return 0;
166
167out_nolock:
168 /*
169 * We didn't take the lock, so that there is a writer, which
170 * is owner or the first waiter of the sem. If it's a waiter,
171 * it will be woken by current owner. Not need to wake anybody.
172 */
173 list_del(&waiter.list);
174 raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
175 return -EINTR;
176}
177
178void __sched __down_read(struct rw_semaphore *sem)
179{
180 __down_read_common(sem, TASK_UNINTERRUPTIBLE);
181}
182
183int __sched __down_read_killable(struct rw_semaphore *sem)
184{
185 return __down_read_common(sem, TASK_KILLABLE);
186}
187
188/*
189 * trylock for reading -- returns 1 if successful, 0 if contention
190 */
191int __down_read_trylock(struct rw_semaphore *sem)
192{
193 unsigned long flags;
194 int ret = 0;
195
196
197 raw_spin_lock_irqsave(&sem->wait_lock, flags);
198
199 if (sem->count >= 0 && list_empty(&sem->wait_list)) {
200 /* granted */
201 sem->count++;
202 ret = 1;
203 }
204
205 raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
206
207 return ret;
208}
209
210/*
211 * get a write lock on the semaphore
212 */
213int __sched __down_write_common(struct rw_semaphore *sem, int state)
214{
215 struct rwsem_waiter waiter;
216 unsigned long flags;
217 int ret = 0;
218
219 raw_spin_lock_irqsave(&sem->wait_lock, flags);
220
221 /* set up my own style of waitqueue */
222 waiter.task = current;
223 waiter.type = RWSEM_WAITING_FOR_WRITE;
224 list_add_tail(&waiter.list, &sem->wait_list);
225
226 /* wait for someone to release the lock */
227 for (;;) {
228 /*
229 * That is the key to support write lock stealing: allows the
230 * task already on CPU to get the lock soon rather than put
231 * itself into sleep and waiting for system woke it or someone
232 * else in the head of the wait list up.
233 */
234 if (sem->count == 0)
235 break;
236 if (signal_pending_state(state, current))
237 goto out_nolock;
238
239 set_current_state(state);
240 raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
241 schedule();
242 raw_spin_lock_irqsave(&sem->wait_lock, flags);
243 }
244 /* got the lock */
245 sem->count = -1;
246 list_del(&waiter.list);
247
248 raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
249
250 return ret;
251
252out_nolock:
253 list_del(&waiter.list);
254 if (!list_empty(&sem->wait_list) && sem->count >= 0)
255 __rwsem_do_wake(sem, 0);
256 raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
257
258 return -EINTR;
259}
260
261void __sched __down_write(struct rw_semaphore *sem)
262{
263 __down_write_common(sem, TASK_UNINTERRUPTIBLE);
264}
265
266int __sched __down_write_killable(struct rw_semaphore *sem)
267{
268 return __down_write_common(sem, TASK_KILLABLE);
269}
270
271/*
272 * trylock for writing -- returns 1 if successful, 0 if contention
273 */
274int __down_write_trylock(struct rw_semaphore *sem)
275{
276 unsigned long flags;
277 int ret = 0;
278
279 raw_spin_lock_irqsave(&sem->wait_lock, flags);
280
281 if (sem->count == 0) {
282 /* got the lock */
283 sem->count = -1;
284 ret = 1;
285 }
286
287 raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
288
289 return ret;
290}
291
292/*
293 * release a read lock on the semaphore
294 */
295void __up_read(struct rw_semaphore *sem)
296{
297 unsigned long flags;
298
299 raw_spin_lock_irqsave(&sem->wait_lock, flags);
300
301 if (--sem->count == 0 && !list_empty(&sem->wait_list))
302 sem = __rwsem_wake_one_writer(sem);
303
304 raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
305}
306
307/*
308 * release a write lock on the semaphore
309 */
310void __up_write(struct rw_semaphore *sem)
311{
312 unsigned long flags;
313
314 raw_spin_lock_irqsave(&sem->wait_lock, flags);
315
316 sem->count = 0;
317 if (!list_empty(&sem->wait_list))
318 sem = __rwsem_do_wake(sem, 1);
319
320 raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
321}
322
323/*
324 * downgrade a write lock into a read lock
325 * - just wake up any readers at the front of the queue
326 */
327void __downgrade_write(struct rw_semaphore *sem)
328{
329 unsigned long flags;
330
331 raw_spin_lock_irqsave(&sem->wait_lock, flags);
332
333 sem->count = 1;
334 if (!list_empty(&sem->wait_list))
335 sem = __rwsem_do_wake(sem, 0);
336
337 raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
338}
339
diff --git a/kernel/locking/rwsem.h b/kernel/locking/rwsem.h
index 067e265fa5c1..45ee00236e03 100644
--- a/kernel/locking/rwsem.h
+++ b/kernel/locking/rwsem.h
@@ -153,7 +153,6 @@ static inline void rwsem_clear_reader_owned(struct rw_semaphore *sem)
153} 153}
154#endif 154#endif
155 155
156#ifdef CONFIG_RWSEM_XCHGADD_ALGORITHM
157/* 156/*
158 * lock for reading 157 * lock for reading
159 */ 158 */
@@ -260,5 +259,3 @@ static inline void __downgrade_write(struct rw_semaphore *sem)
260 if (tmp < 0) 259 if (tmp < 0)
261 rwsem_downgrade_wake(sem); 260 rwsem_downgrade_wake(sem);
262} 261}
263
264#endif /* CONFIG_RWSEM_XCHGADD_ALGORITHM */