summaryrefslogtreecommitdiffstats
path: root/arch/ia64
diff options
context:
space:
mode:
authorWaiman Long <longman@redhat.com>2019-03-22 10:30:06 -0400
committerIngo Molnar <mingo@kernel.org>2019-04-03 08:50:50 -0400
commit46ad0840b1584b92b5ff2cc3ed0b011dd6b8e0f1 (patch)
tree78322537b33b4aa4cd4230bf2603e46f214bcf9a /arch/ia64
parenta1247d06d01045d7ab2882a9c074fbf21137c690 (diff)
locking/rwsem: Remove arch specific rwsem files
As the generic rwsem-xadd code is using the appropriate acquire and release versions of the atomic operations, the arch specific rwsem.h files will not be that much faster than the generic code as long as the atomic functions are properly implemented. So we can remove those arch specific rwsem.h and stop building asm/rwsem.h to reduce maintenance effort. Currently, only x86, alpha and ia64 have implemented architecture specific fast paths. I don't have access to alpha and ia64 systems for testing, but they are legacy systems that are not likely to be updated to the latest kernel anyway. By using a rwsem microbenchmark, the total locking rates on a 4-socket 56-core 112-thread x86-64 system before and after the patch were as follows (mixed means equal # of read and write locks): Before Patch After Patch # of Threads wlock rlock mixed wlock rlock mixed ------------ ----- ----- ----- ----- ----- ----- 1 29,201 30,143 29,458 28,615 30,172 29,201 2 6,807 13,299 1,171 7,725 15,025 1,804 4 6,504 12,755 1,520 7,127 14,286 1,345 8 6,762 13,412 764 6,826 13,652 726 16 6,693 15,408 662 6,599 15,938 626 32 6,145 15,286 496 5,549 15,487 511 64 5,812 15,495 60 5,858 15,572 60 There were some run-to-run variations for the multi-thread tests. For x86-64, using the generic C code fast path seems to be a little bit faster than the assembly version with low lock contention. Looking at the assembly version of the fast paths, there are assembly to/from C code wrappers that save and restore all the callee-clobbered registers (7 registers on x86-64). The assembly generated from the generic C code doesn't need to do that. That may explain the slight performance gain here. The generic asm rwsem.h can also be merged into kernel/locking/rwsem.h with no code change as no other code other than those under kernel/locking needs to access the internal rwsem macros and functions. 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: Peter Zijlstra <peterz@infradead.org> 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-2-longman@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/ia64')
-rw-r--r--arch/ia64/include/asm/rwsem.h172
1 files changed, 0 insertions, 172 deletions
diff --git a/arch/ia64/include/asm/rwsem.h b/arch/ia64/include/asm/rwsem.h
deleted file mode 100644
index 917910607e0e..000000000000
--- a/arch/ia64/include/asm/rwsem.h
+++ /dev/null
@@ -1,172 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * R/W semaphores for ia64
4 *
5 * Copyright (C) 2003 Ken Chen <kenneth.w.chen@intel.com>
6 * Copyright (C) 2003 Asit Mallick <asit.k.mallick@intel.com>
7 * Copyright (C) 2005 Christoph Lameter <cl@linux.com>
8 *
9 * Based on asm-i386/rwsem.h and other architecture implementation.
10 *
11 * The MSW of the count is the negated number of active writers and
12 * waiting lockers, and the LSW is the total number of active locks.
13 *
14 * The lock count is initialized to 0 (no active and no waiting lockers).
15 *
16 * When a writer subtracts WRITE_BIAS, it'll get 0xffffffff00000001 for
17 * the case of an uncontended lock. Readers increment by 1 and see a positive
18 * value when uncontended, negative if there are writers (and maybe) readers
19 * waiting (in which case it goes to sleep).
20 */
21
22#ifndef _ASM_IA64_RWSEM_H
23#define _ASM_IA64_RWSEM_H
24
25#ifndef _LINUX_RWSEM_H
26#error "Please don't include <asm/rwsem.h> directly, use <linux/rwsem.h> instead."
27#endif
28
29#include <asm/intrinsics.h>
30
31#define RWSEM_UNLOCKED_VALUE __IA64_UL_CONST(0x0000000000000000)
32#define RWSEM_ACTIVE_BIAS (1L)
33#define RWSEM_ACTIVE_MASK (0xffffffffL)
34#define RWSEM_WAITING_BIAS (-0x100000000L)
35#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
36#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
37
38/*
39 * lock for reading
40 */
41static inline int
42___down_read (struct rw_semaphore *sem)
43{
44 long result = ia64_fetchadd8_acq((unsigned long *)&sem->count.counter, 1);
45
46 return (result < 0);
47}
48
49static inline void
50__down_read (struct rw_semaphore *sem)
51{
52 if (___down_read(sem))
53 rwsem_down_read_failed(sem);
54}
55
56static inline int
57__down_read_killable (struct rw_semaphore *sem)
58{
59 if (___down_read(sem))
60 if (IS_ERR(rwsem_down_read_failed_killable(sem)))
61 return -EINTR;
62
63 return 0;
64}
65
66/*
67 * lock for writing
68 */
69static inline long
70___down_write (struct rw_semaphore *sem)
71{
72 long old, new;
73
74 do {
75 old = atomic_long_read(&sem->count);
76 new = old + RWSEM_ACTIVE_WRITE_BIAS;
77 } while (atomic_long_cmpxchg_acquire(&sem->count, old, new) != old);
78
79 return old;
80}
81
82static inline void
83__down_write (struct rw_semaphore *sem)
84{
85 if (___down_write(sem))
86 rwsem_down_write_failed(sem);
87}
88
89static inline int
90__down_write_killable (struct rw_semaphore *sem)
91{
92 if (___down_write(sem)) {
93 if (IS_ERR(rwsem_down_write_failed_killable(sem)))
94 return -EINTR;
95 }
96
97 return 0;
98}
99
100/*
101 * unlock after reading
102 */
103static inline void
104__up_read (struct rw_semaphore *sem)
105{
106 long result = ia64_fetchadd8_rel((unsigned long *)&sem->count.counter, -1);
107
108 if (result < 0 && (--result & RWSEM_ACTIVE_MASK) == 0)
109 rwsem_wake(sem);
110}
111
112/*
113 * unlock after writing
114 */
115static inline void
116__up_write (struct rw_semaphore *sem)
117{
118 long old, new;
119
120 do {
121 old = atomic_long_read(&sem->count);
122 new = old - RWSEM_ACTIVE_WRITE_BIAS;
123 } while (atomic_long_cmpxchg_release(&sem->count, old, new) != old);
124
125 if (new < 0 && (new & RWSEM_ACTIVE_MASK) == 0)
126 rwsem_wake(sem);
127}
128
129/*
130 * trylock for reading -- returns 1 if successful, 0 if contention
131 */
132static inline int
133__down_read_trylock (struct rw_semaphore *sem)
134{
135 long tmp;
136 while ((tmp = atomic_long_read(&sem->count)) >= 0) {
137 if (tmp == atomic_long_cmpxchg_acquire(&sem->count, tmp, tmp+1)) {
138 return 1;
139 }
140 }
141 return 0;
142}
143
144/*
145 * trylock for writing -- returns 1 if successful, 0 if contention
146 */
147static inline int
148__down_write_trylock (struct rw_semaphore *sem)
149{
150 long tmp = atomic_long_cmpxchg_acquire(&sem->count,
151 RWSEM_UNLOCKED_VALUE, RWSEM_ACTIVE_WRITE_BIAS);
152 return tmp == RWSEM_UNLOCKED_VALUE;
153}
154
155/*
156 * downgrade write lock to read lock
157 */
158static inline void
159__downgrade_write (struct rw_semaphore *sem)
160{
161 long old, new;
162
163 do {
164 old = atomic_long_read(&sem->count);
165 new = old - RWSEM_WAITING_BIAS;
166 } while (atomic_long_cmpxchg_release(&sem->count, old, new) != old);
167
168 if (old < 0)
169 rwsem_downgrade_wake(sem);
170}
171
172#endif /* _ASM_IA64_RWSEM_H */