History

Merge branch 'locking-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull locking and atomic updates from Ingo Molnar: "Main changes in this cycle are: - Extend atomic primitives with coherent logic op primitives (atomic_{or,and,xor}()) and deprecate the old partial APIs (atomic_{set,clear}_mask()) The old ops were incoherent with incompatible signatures across architectures and with incomplete support. Now every architecture supports the primitives consistently (by Peter Zijlstra) - Generic support for 'relaxed atomics': - _acquire/release/relaxed() flavours of xchg(), cmpxchg() and {add,sub}_return() - atomic_read_acquire() - atomic_set_release() This came out of porting qwrlock code to arm64 (by Will Deacon) - Clean up the fragile static_key APIs that were causing repeat bugs, by introducing a new one: DEFINE_STATIC_KEY_TRUE(name); DEFINE_STATIC_KEY_FALSE(name); which define a key of different types with an initial true/false value. Then allow: static_branch_likely() static_branch_unlikely() to take a key of either type and emit the right instruction for the case. To be able to know the 'type' of the static key we encode it in the jump entry (by Peter Zijlstra) - Static key self-tests (by Jason Baron) - qrwlock optimizations (by Waiman Long) - small futex enhancements (by Davidlohr Bueso) - ... and misc other changes" * 'locking-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (63 commits) jump_label/x86: Work around asm build bug on older/backported GCCs locking, ARM, atomics: Define our SMP atomics in terms of _relaxed() operations locking, include/llist: Use linux/atomic.h instead of asm/cmpxchg.h locking/qrwlock: Make use of _{acquire|release|relaxed}() atomics locking/qrwlock: Implement queue_write_unlock() using smp_store_release() locking/lockref: Remove homebrew cmpxchg64_relaxed() macro definition locking, asm-generic: Add _{relaxed|acquire|release}() variants for 'atomic_long_t' locking, asm-generic: Rework atomic-long.h to avoid bulk code duplication locking/atomics: Add _{acquire|release|relaxed}() variants of some atomic operations locking, compiler.h: Cast away attributes in the WRITE_ONCE() magic locking/static_keys: Make verify_keys() static jump label, locking/static_keys: Update docs locking/static_keys: Provide a selftest jump_label: Provide a self-test s390/uaccess, locking/static_keys: employ static_branch_likely() x86, tsc, locking/static_keys: Employ static_branch_likely() locking/static_keys: Add selftest locking/static_keys: Add a new static_key interface locking/static_keys: Rework update logic locking/static_keys: Add static_key_{en,dis}able() helpers ...

Linus Torvalds committed 11 years ago

Commit ca520ca2 parents 4c12ab7 d420acd139 files · +2425 −3585Browse files

Unified · Split

139 files
  1. Documentation/atomic_ops.txt +3 −1
  2. Documentation/fault-injection/fault-injection.txt +11 −0
  3. Documentation/memory-barriers.txt +3 −3
  4. Documentation/static-keys.txt +52 −47
  5. arch/Kconfig +6 −0
  6. arch/alpha/include/asm/atomic.h +27 −15
  7. arch/arc/include/asm/atomic.h +6 −2
  8. arch/arm/include/asm/atomic.h +30 −21
  9. arch/arm/include/asm/barrier.h +2 −2
  10. arch/arm/include/asm/cmpxchg.h +8 −39
  11. arch/arm/include/asm/jump_label.h +17 −8
  12. arch/arm/kernel/jump_label.c +1 −1
  13. arch/arm64/include/asm/atomic.h +14 −0
  14. arch/arm64/include/asm/barrier.h +2 −2
  15. arch/arm64/include/asm/jump_label.h +16 −2
  16. arch/arm64/kernel/jump_label.c +1 −1
  17. arch/avr32/include/asm/atomic.h +12 −0
  18. arch/blackfin/include/asm/atomic.h +9 −7
  19. arch/blackfin/kernel/bfin_ksyms.c +4 −3
  20. arch/blackfin/mach-bf561/atomic.S +15 −15
  21. arch/blackfin/mach-common/smp.c +1 −1
  22. arch/frv/include/asm/atomic.h +54 −53
  23. arch/frv/include/asm/atomic_defs.h +172 −0
  24. arch/frv/include/asm/bitops.h +10 −89
  25. arch/frv/kernel/dma.c +3 −3
  26. arch/frv/kernel/frv_ksyms.c +0 −5
  27. arch/frv/lib/Makefile +1 −1
  28. arch/frv/lib/atomic-lib.c +7 −0
  29. arch/frv/lib/atomic-ops.S +0 −110
  30. arch/frv/lib/atomic64-ops.S +0 −94
  31. arch/h8300/include/asm/atomic.h +35 −102
  32. arch/hexagon/include/asm/atomic.h +4 −0
  33. arch/ia64/include/asm/atomic.h +20 −4
  34. arch/ia64/include/asm/barrier.h +2 −2
  35. arch/m32r/include/asm/atomic.h +4 −41
  36. arch/m32r/kernel/smp.c +2 −2
  37. arch/m68k/include/asm/atomic.h +4 −10
  38. arch/metag/include/asm/atomic_lnkget.h +4 −34
  39. arch/metag/include/asm/atomic_lock1.h +3 −20
  40. arch/metag/include/asm/barrier.h +2 −2
  41. arch/mips/include/asm/atomic.h +7 −0
  42. arch/mips/include/asm/barrier.h +2 −2
  43. arch/mips/include/asm/jump_label.h +17 −2
  44. arch/mips/kernel/jump_label.c +1 −1
  45. arch/mn10300/include/asm/atomic.h +4 −67
  46. arch/mn10300/mm/tlb-smp.c +1 −1
  47. arch/parisc/configs/c8000_defconfig +0 −1
  48. arch/parisc/configs/generic-32bit_defconfig +0 −1
  49. arch/parisc/include/asm/atomic.h +7 −0
  50. arch/powerpc/include/asm/atomic.h +7 −0
  51. arch/powerpc/include/asm/barrier.h +2 −2
  52. arch/powerpc/include/asm/jump_label.h +17 −2
  53. arch/powerpc/kernel/jump_label.c +1 −1
  54. arch/powerpc/kernel/misc_32.S +0 −19
  55. arch/s390/include/asm/atomic.h +24 −17
  56. arch/s390/include/asm/barrier.h +2 −2
  57. arch/s390/include/asm/jump_label.h +17 −2
  58. arch/s390/kernel/jump_label.c +1 −1
  59. arch/s390/kernel/time.c +2 −2
  60. arch/s390/kvm/interrupt.c +15 −15
  61. arch/s390/kvm/kvm-s390.c +16 −16
  62. arch/s390/lib/uaccess.c +6 −6
  63. arch/sh/include/asm/atomic-grb.h +4 −39
  64. arch/sh/include/asm/atomic-irq.h +3 −18
  65. arch/sh/include/asm/atomic-llsc.h +3 −28
  66. arch/sparc/include/asm/atomic_32.h +3 −1
  67. arch/sparc/include/asm/atomic_64.h +4 −0
  68. arch/sparc/include/asm/barrier_64.h +2 −2
  69. arch/sparc/include/asm/jump_label.h +26 −9
  70. arch/sparc/kernel/jump_label.c +1 −1
  71. arch/sparc/lib/atomic32.c +19 −3
  72. arch/sparc/lib/atomic_64.S +6 −0
  73. arch/sparc/lib/ksyms.c +3 −0
  74. arch/tile/include/asm/atomic_32.h +28 −0
  75. arch/tile/include/asm/atomic_64.h +40 −0
  76. arch/tile/lib/atomic_32.c +23 −0
  77. arch/tile/lib/atomic_asm_32.S +4 −0
  78. arch/x86/include/asm/atomic.h +15 −10
  79. arch/x86/include/asm/atomic64_32.h +14 −0
  80. arch/x86/include/asm/atomic64_64.h +15 −0
  81. arch/x86/include/asm/barrier.h +4 −4
  82. arch/x86/include/asm/jump_label.h +20 −3
  83. arch/x86/include/asm/qrwlock.h +0 −10
  84. arch/x86/kernel/jump_label.c +1 −1
  85. arch/x86/kernel/tsc.c +10 −12
  86. arch/xtensa/configs/iss_defconfig +0 −1
  87. arch/xtensa/include/asm/atomic.h +4 −69
  88. drivers/gpu/drm/i915/i915_drv.c +1 −1
  89. drivers/gpu/drm/i915/i915_gem.c +1 −1
  90. drivers/gpu/drm/i915/i915_irq.c +2 −2
  91. drivers/s390/scsi/zfcp_aux.c +1 −1
  92. drivers/s390/scsi/zfcp_erp.c +31 −31
  93. drivers/s390/scsi/zfcp_fc.c +4 −4
  94. drivers/s390/scsi/zfcp_fsf.c +13 −13
  95. drivers/s390/scsi/zfcp_qdio.c +7 −7
  96. include/asm-generic/atomic-long.h +93 −170
  97. include/asm-generic/atomic.h +6 −5
  98. include/asm-generic/atomic64.h +4 −0
  99. include/asm-generic/barrier.h +2 −2
  100. include/asm-generic/qrwlock.h +35 −43
  101. include/linux/atomic.h +348 −13
  102. include/linux/compiler.h +6 −1
  103. include/linux/jump_label.h +210 −51
  104. include/linux/llist.h +1 −1
  105. kernel/futex.c +96 −4
  106. kernel/jump_label.c +109 −49
  107. kernel/locking/Makefile +0 −1
  108. kernel/locking/qrwlock.c +22 −25
  109. kernel/locking/qspinlock.c +3 −3
  110. kernel/locking/qspinlock_paravirt.h +73 −29
  111. kernel/locking/rtmutex-tester.c +0 −420
  112. kernel/locking/rtmutex.c +1 −1
  113. kernel/locking/rtmutex_common.h +0 −22
  114. kernel/sched/core.c +2 −4
  115. lib/Kconfig.debug +16 −6
  116. lib/Makefile +2 −0
  117. lib/atomic64.c +3 −0
  118. lib/atomic64_test.c +47 −21
  119. lib/lockref.c +0 −8
  120. lib/test_static_key_base.c +68 −0
  121. lib/test_static_keys.c +225 −0
  122. scripts/rt-tester/check-all.sh +0 −21
  123. scripts/rt-tester/rt-tester.py +0 −218
  124. scripts/rt-tester/t2-l1-2rt-sameprio.tst +0 −94
  125. scripts/rt-tester/t2-l1-pi.tst +0 −77
  126. scripts/rt-tester/t2-l1-signal.tst +0 −72
  127. scripts/rt-tester/t2-l2-2rt-deadlock.tst +0 −84
  128. scripts/rt-tester/t3-l1-pi-1rt.tst +0 −87
  129. scripts/rt-tester/t3-l1-pi-2rt.tst +0 −88
  130. scripts/rt-tester/t3-l1-pi-3rt.tst +0 −87
  131. scripts/rt-tester/t3-l1-pi-signal.tst +0 −93
  132. scripts/rt-tester/t3-l1-pi-steal.tst +0 −91
  133. scripts/rt-tester/t3-l2-pi.tst +0 −87
  134. scripts/rt-tester/t4-l2-pi-deboost.tst +0 −118
  135. scripts/rt-tester/t5-l4-pi-boost-deboost-setsched.tst +0 −178
  136. scripts/rt-tester/t5-l4-pi-boost-deboost.tst +0 −138
  137. tools/testing/selftests/Makefile +1 −0
  138. tools/testing/selftests/static_keys/Makefile +8 −0
  139. tools/testing/selftests/static_keys/test_static_keys.sh +16 −0
Documentation/atomic_ops.txt+3−1
@@ -266,7 +266,9 @@ with the given old and new values. Like all atomic_xxx operations, · 265 unmodified lines
266266 atomic_cmpxchg will only satisfy its atomicity semantics as long as all
267267 other accesses of *v are performed through atomic_xxx operations.
268268
269−atomic_cmpxchg must provide explicit memory barriers around the operation.
269+atomic_cmpxchg must provide explicit memory barriers around the operation,
270+although if the comparison fails then no memory ordering guarantees are
271+required.
270272
271273 The semantics for atomic_cmpxchg are the same as those defined for 'cas'
272274 below.
Documentation/fault-injection/fault-injection.txt+11−0
@@ -15,6 +15,10 @@ o fail_page_alloc · 14 unmodified lines
1515
1616 injects page allocation failures. (alloc_pages(), get_free_pages(), ...)
1717
18+o fail_futex
19+
20+ injects futex deadlock and uaddr fault errors.
21+
1822 o fail_make_request
1923
2024 injects disk IO errors on devices permitted by setting
@@ -113,6 +117,12 @@ configuration of fault-injection capabilities. · 92 unmodified lines
113117 specifies the minimum page allocation order to be injected
114118 failures.
115119
120+- /sys/kernel/debug/fail_futex/ignore-private:
121+
122+ Format: { 'Y' | 'N' }
123+ default is 'N', setting it to 'Y' will disable failure injections
124+ when dealing with private (address space) futexes.
125+
116126 o Boot option
117127
118128 In order to inject faults while debugfs is not available (early boot time),
@@ -121,6 +131,7 @@ use the boot option: · 2 unmodified lines
121131 failslab=
122132 fail_page_alloc=
123133 fail_make_request=
134+ fail_futex=
124135 mmc_core.fail_request=<interval>,<probability>,<space>,<times>
125136
126137 How to add new fault injection capability
Documentation/memory-barriers.txt+3−3
@@ -2327,9 +2327,7 @@ about the state (old or new) implies an SMP-conditional general memory barrier · 2326 unmodified lines
23272327 explicit lock operations, described later). These include:
23282328
23292329 xchg();
2330− cmpxchg();
23312330 atomic_xchg(); atomic_long_xchg();
2332− atomic_cmpxchg(); atomic_long_cmpxchg();
23332331 atomic_inc_return(); atomic_long_inc_return();
23342332 atomic_dec_return(); atomic_long_dec_return();
23352333 atomic_add_return(); atomic_long_add_return();
@@ -2342,7 +2340,9 @@ explicit lock operations, described later). These include: · 6 unmodified lines
23422340 test_and_clear_bit();
23432341 test_and_change_bit();
23442342
2345− /* when succeeds (returns 1) */
2343+ /* when succeeds */
2344+ cmpxchg();
2345+ atomic_cmpxchg(); atomic_long_cmpxchg();
23462346 atomic_add_unless(); atomic_long_add_unless();
23472347
23482348 These are used for such things as implementing ACQUIRE-class and RELEASE-class
Documentation/static-keys.txt+52−47
@@ -1,7 +1,22 @@
11 Static Keys
22 -----------
33
4−By: Jason Baron <jbaron@redhat.com>
4+DEPRECATED API:
5+
6+The use of 'struct static_key' directly, is now DEPRECATED. In addition
7+static_key_{true,false}() is also DEPRECATED. IE DO NOT use the following:
8+
9+struct static_key false = STATIC_KEY_INIT_FALSE;
10+struct static_key true = STATIC_KEY_INIT_TRUE;
11+static_key_true()
12+static_key_false()
13+
14+The updated API replacements are:
15+
16+DEFINE_STATIC_KEY_TRUE(key);
17+DEFINE_STATIC_KEY_FALSE(key);
18+static_key_likely()
19+statick_key_unlikely()
520
621 0) Abstract
722
@@ -9,22 +24,22 @@ Static keys allows the inclusion of seldom used features in · 1 unmodified line
924 performance-sensitive fast-path kernel code, via a GCC feature and a code
1025 patching technique. A quick example:
1126
12− struct static_key key = STATIC_KEY_INIT_FALSE;
27+ DEFINE_STATIC_KEY_FALSE(key);
1328
1429 ...
1530
16− if (static_key_false(&key))
31+ if (static_branch_unlikely(&key))
1732 do unlikely code
1833 else
1934 do likely code
2035
2136 ...
22− static_key_slow_inc();
37+ static_branch_enable(&key);
2338 ...
24− static_key_slow_inc();
39+ static_branch_disable(&key);
2540 ...
2641
27−The static_key_false() branch will be generated into the code with as little
42+The static_branch_unlikely() branch will be generated into the code with as little
2843 impact to the likely code path as possible.
2944
3045
@@ -56,7 +71,7 @@ the branch site to change the branch direction. · 25 unmodified lines
5671
5772 For example, if we have a simple branch that is disabled by default:
5873
59− if (static_key_false(&key))
74+ if (static_branch_unlikely(&key))
6075 printk("I am the true branch\n");
6176
6277 Thus, by default the 'printk' will not be emitted. And the code generated will
@@ -75,68 +90,55 @@ the basis for the static keys facility. · 12 unmodified lines
7590
7691 In order to make use of this optimization you must first define a key:
7792
78− struct static_key key;
79−
80−Which is initialized as:
81−
82− struct static_key key = STATIC_KEY_INIT_TRUE;
93+ DEFINE_STATIC_KEY_TRUE(key);
8394
8495 or:
8596
86− struct static_key key = STATIC_KEY_INIT_FALSE;
97+ DEFINE_STATIC_KEY_FALSE(key);
98+
8799
88−If the key is not initialized, it is default false. The 'struct static_key',
89−must be a 'global'. That is, it can't be allocated on the stack or dynamically
100+The key must be global, that is, it can't be allocated on the stack or dynamically
90101 allocated at run-time.
91102
92103 The key is then used in code as:
93104
94− if (static_key_false(&key))
105+ if (static_branch_unlikely(&key))
95106 do unlikely code
96107 else
97108 do likely code
98109
99110 Or:
100111
101− if (static_key_true(&key))
112+ if (static_branch_likely(&key))
102113 do likely code
103114 else
104115 do unlikely code
105116
106−A key that is initialized via 'STATIC_KEY_INIT_FALSE', must be used in a
107−'static_key_false()' construct. Likewise, a key initialized via
108−'STATIC_KEY_INIT_TRUE' must be used in a 'static_key_true()' construct. A
109−single key can be used in many branches, but all the branches must match the
110−way that the key has been initialized.
117+Keys defined via DEFINE_STATIC_KEY_TRUE(), or DEFINE_STATIC_KEY_FALSE, may
118+be used in either static_branch_likely() or static_branch_unlikely()
119+statemnts.
111120
112−The branch(es) can then be switched via:
121+Branch(es) can be set true via:
113122
114− static_key_slow_inc(&key);
115− ...
116− static_key_slow_dec(&key);
123+static_branch_enable(&key);
117124
118−Thus, 'static_key_slow_inc()' means 'make the branch true', and
119−'static_key_slow_dec()' means 'make the branch false' with appropriate
120−reference counting. For example, if the key is initialized true, a
121−static_key_slow_dec(), will switch the branch to false. And a subsequent
122−static_key_slow_inc(), will change the branch back to true. Likewise, if the
123−key is initialized false, a 'static_key_slow_inc()', will change the branch to
124−true. And then a 'static_key_slow_dec()', will again make the branch false.
125+or false via:
126+
127+static_branch_disable(&key);
125128
126−An example usage in the kernel is the implementation of tracepoints:
129+The branch(es) can then be switched via reference counts:
127130
128− static inline void trace_##name(proto) \
129− { \
130− if (static_key_false(&__tracepoint_##name.key)) \
131− __DO_TRACE(&__tracepoint_##name, \
132− TP_PROTO(data_proto), \
133− TP_ARGS(data_args), \
134− TP_CONDITION(cond)); \
135− }
131+ static_branch_inc(&key);
132+ ...
133+ static_branch_dec(&key);
136134
137−Tracepoints are disabled by default, and can be placed in performance critical
138−pieces of the kernel. Thus, by using a static key, the tracepoints can have
139−absolutely minimal impact when not in use.
135+Thus, 'static_branch_inc()' means 'make the branch true', and
136+'static_branch_dec()' means 'make the branch false' with appropriate
137+reference counting. For example, if the key is initialized true, a
138+static_branch_dec(), will switch the branch to false. And a subsequent
139+static_branch_inc(), will change the branch back to true. Likewise, if the
140+key is initialized false, a 'static_branch_inc()', will change the branch to
141+true. And then a 'static_branch_dec()', will again make the branch false.
140142
141143
142144 4) Architecture level code patching interface, 'jump labels'
@@ -150,9 +152,12 @@ simply fall back to a traditional, load, test, and jump sequence. · 7 unmodified lines
150152
151153 * #define JUMP_LABEL_NOP_SIZE, see: arch/x86/include/asm/jump_label.h
152154
153−* __always_inline bool arch_static_branch(struct static_key *key), see:
155+* __always_inline bool arch_static_branch(struct static_key *key, bool branch), see:
154156 arch/x86/include/asm/jump_label.h
155157
158+* __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch),
159+ see: arch/x86/include/asm/jump_label.h
160+
156161 * void arch_jump_label_transform(struct jump_entry *entry, enum jump_label_type type),
157162 see: arch/x86/kernel/jump_label.c
158163
@@ -173,7 +178,7 @@ SYSCALL_DEFINE0(getppid) · 14 unmodified lines
173178 {
174179 int pid;
175180
176−+ if (static_key_false(&key))
181++ if (static_branch_unlikely(&key))
177182 + printk("I am the true branch\n");
178183
179184 rcu_read_lock();
arch/Kconfig+6−0
@@ -71,6 +71,12 @@ config JUMP_LABEL · 70 unmodified lines
7171 ( On 32-bit x86, the necessary options added to the compiler
7272 flags may increase the size of the kernel slightly. )
7373
74+config STATIC_KEYS_SELFTEST
75+ bool "Static key selftest"
76+ depends on JUMP_LABEL
77+ help
78+ Boot time self-test of the branch patching code.
79+
7480 config OPTPROBES
7581 def_bool y
7682 depends on KPROBES && HAVE_OPTPROBES
arch/alpha/include/asm/atomic.h+27−15
@@ -29,13 +29,13 @@ · 28 unmodified lines
2929 * branch back to restart the operation.
3030 */
3131
32−#define ATOMIC_OP(op) \
32+#define ATOMIC_OP(op, asm_op) \
3333 static __inline__ void atomic_##op(int i, atomic_t * v) \
3434 { \
3535 unsigned long temp; \
3636 __asm__ __volatile__( \
3737 "1: ldl_l %0,%1\n" \
38− " " #op "l %0,%2,%0\n" \
38+ " " #asm_op " %0,%2,%0\n" \
3939 " stl_c %0,%1\n" \
4040 " beq %0,2f\n" \
4141 ".subsection 2\n" \
@@ -45,15 +45,15 @@ static __inline__ void atomic_##op(int i, atomic_t * v) \ · 3 unmodified lines
4545 :"Ir" (i), "m" (v->counter)); \
4646 } \
4747
48−#define ATOMIC_OP_RETURN(op) \
48+#define ATOMIC_OP_RETURN(op, asm_op) \
4949 static inline int atomic_##op##_return(int i, atomic_t *v) \
5050 { \
5151 long temp, result; \
5252 smp_mb(); \
5353 __asm__ __volatile__( \
5454 "1: ldl_l %0,%1\n" \
55− " " #op "l %0,%3,%2\n" \
56− " " #op "l %0,%3,%0\n" \
55+ " " #asm_op " %0,%3,%2\n" \
56+ " " #asm_op " %0,%3,%0\n" \
5757 " stl_c %0,%1\n" \
5858 " beq %0,2f\n" \
5959 ".subsection 2\n" \
@@ -65,13 +65,13 @@ static inline int atomic_##op##_return(int i, atomic_t *v) \ · 5 unmodified lines
6565 return result; \
6666 }
6767
68−#define ATOMIC64_OP(op) \
68+#define ATOMIC64_OP(op, asm_op) \
6969 static __inline__ void atomic64_##op(long i, atomic64_t * v) \
7070 { \
7171 unsigned long temp; \
7272 __asm__ __volatile__( \
7373 "1: ldq_l %0,%1\n" \
74− " " #op "q %0,%2,%0\n" \
74+ " " #asm_op " %0,%2,%0\n" \
7575 " stq_c %0,%1\n" \
7676 " beq %0,2f\n" \
7777 ".subsection 2\n" \
@@ -81,15 +81,15 @@ static __inline__ void atomic64_##op(long i, atomic64_t * v) \ · 3 unmodified lines
8181 :"Ir" (i), "m" (v->counter)); \
8282 } \
8383
84−#define ATOMIC64_OP_RETURN(op) \
84+#define ATOMIC64_OP_RETURN(op, asm_op) \
8585 static __inline__ long atomic64_##op##_return(long i, atomic64_t * v) \
8686 { \
8787 long temp, result; \
8888 smp_mb(); \
8989 __asm__ __volatile__( \
9090 "1: ldq_l %0,%1\n" \
91− " " #op "q %0,%3,%2\n" \
92− " " #op "q %0,%3,%0\n" \
91+ " " #asm_op " %0,%3,%2\n" \
92+ " " #asm_op " %0,%3,%0\n" \
9393 " stq_c %0,%1\n" \
9494 " beq %0,2f\n" \
9595 ".subsection 2\n" \
@@ -101,15 +101,27 @@ static __inline__ long atomic64_##op##_return(long i, atomic64_t * v) \ · 5 unmodified lines
101101 return result; \
102102 }
103103
104−#define ATOMIC_OPS(opg) \
105− ATOMIC_OP(opg) \
106− ATOMIC_OP_RETURN(opg) \
107− ATOMIC64_OP(opg) \
108− ATOMIC64_OP_RETURN(opg)
104+#define ATOMIC_OPS(op) \
105+ ATOMIC_OP(op, op##l) \
106+ ATOMIC_OP_RETURN(op, op##l) \
107+ ATOMIC64_OP(op, op##q) \
108+ ATOMIC64_OP_RETURN(op, op##q)
109109
110110 ATOMIC_OPS(add)
111111 ATOMIC_OPS(sub)
112112
113+#define atomic_andnot atomic_andnot
114+#define atomic64_andnot atomic64_andnot
115+
116+ATOMIC_OP(and, and)
117+ATOMIC_OP(andnot, bic)
118+ATOMIC_OP(or, bis)
119+ATOMIC_OP(xor, xor)
120+ATOMIC64_OP(and, and)
121+ATOMIC64_OP(andnot, bic)
122+ATOMIC64_OP(or, bis)
123+ATOMIC64_OP(xor, xor)
124+
113125 #undef ATOMIC_OPS
114126 #undef ATOMIC64_OP_RETURN
115127 #undef ATOMIC64_OP
arch/arc/include/asm/atomic.h+6−2
@@ -172,9 +172,13 @@ static inline int atomic_##op##_return(int i, atomic_t *v) \ · 171 unmodified lines
172172
173173 ATOMIC_OPS(add, +=, add)
174174 ATOMIC_OPS(sub, -=, sub)
175−ATOMIC_OP(and, &=, and)
176175
177−#define atomic_clear_mask(mask, v) atomic_and(~(mask), (v))
176+#define atomic_andnot atomic_andnot
177+
178+ATOMIC_OP(and, &=, and)
179+ATOMIC_OP(andnot, &= ~, bic)
180+ATOMIC_OP(or, |=, or)
181+ATOMIC_OP(xor, ^=, xor)
178182
179183 #undef ATOMIC_OPS
180184 #undef ATOMIC_OP_RETURN
arch/arm/include/asm/atomic.h+30−21
@@ -57,12 +57,11 @@ static inline void atomic_##op(int i, atomic_t *v) \ · 56 unmodified lines
5757 } \
5858
5959 #define ATOMIC_OP_RETURN(op, c_op, asm_op) \
60−static inline int atomic_##op##_return(int i, atomic_t *v) \
60+static inline int atomic_##op##_return_relaxed(int i, atomic_t *v) \
6161 { \
6262 unsigned long tmp; \
6363 int result; \
6464 \
65− smp_mb(); \
6665 prefetchw(&v->counter); \
6766 \
6867 __asm__ __volatile__("@ atomic_" #op "_return\n" \
@@ -75,17 +74,17 @@ static inline int atomic_##op##_return(int i, atomic_t *v) \ · 6 unmodified lines
7574 : "r" (&v->counter), "Ir" (i) \
7675 : "cc"); \
7776 \
78− smp_mb(); \
79− \
8077 return result; \
8178 }
8279
83−static inline int atomic_cmpxchg(atomic_t *ptr, int old, int new)
80+#define atomic_add_return_relaxed atomic_add_return_relaxed
81+#define atomic_sub_return_relaxed atomic_sub_return_relaxed
82+
83+static inline int atomic_cmpxchg_relaxed(atomic_t *ptr, int old, int new)
8484 {
8585 int oldval;
8686 unsigned long res;
8787
88− smp_mb();
8988 prefetchw(&ptr->counter);
9089
9190 do {
@@ -99,10 +98,9 @@ static inline int atomic_cmpxchg(atomic_t *ptr, int old, int new) · 7 unmodified lines
9998 : "cc");
10099 } while (res);
101100
102− smp_mb();
103−
104101 return oldval;
105102 }
103+#define atomic_cmpxchg_relaxed atomic_cmpxchg_relaxed
106104
107105 static inline int __atomic_add_unless(atomic_t *v, int a, int u)
108106 {
@@ -194,6 +192,13 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u) · 85 unmodified lines
194192 ATOMIC_OPS(add, +=, add)
195193 ATOMIC_OPS(sub, -=, sub)
196194
195+#define atomic_andnot atomic_andnot
196+
197+ATOMIC_OP(and, &=, and)
198+ATOMIC_OP(andnot, &= ~, bic)
199+ATOMIC_OP(or, |=, orr)
200+ATOMIC_OP(xor, ^=, eor)
201+
197202 #undef ATOMIC_OPS
198203 #undef ATOMIC_OP_RETURN
199204 #undef ATOMIC_OP
@@ -290,12 +295,12 @@ static inline void atomic64_##op(long long i, atomic64_t *v) \ · 90 unmodified lines
290295 } \
291296
292297 #define ATOMIC64_OP_RETURN(op, op1, op2) \
293−static inline long long atomic64_##op##_return(long long i, atomic64_t *v) \
298+static inline long long \
299+atomic64_##op##_return_relaxed(long long i, atomic64_t *v) \
294300 { \
295301 long long result; \
296302 unsigned long tmp; \
297303 \
298− smp_mb(); \
299304 prefetchw(&v->counter); \
300305 \
301306 __asm__ __volatile__("@ atomic64_" #op "_return\n" \
@@ -309,8 +314,6 @@ static inline long long atomic64_##op##_return(long long i, atomic64_t *v) \ · 7 unmodified lines
309314 : "r" (&v->counter), "r" (i) \
310315 : "cc"); \
311316 \
312− smp_mb(); \
313− \
314317 return result; \
315318 }
316319
@@ -321,17 +324,26 @@ static inline long long atomic64_##op##_return(long long i, atomic64_t *v) \ · 4 unmodified lines
321324 ATOMIC64_OPS(add, adds, adc)
322325 ATOMIC64_OPS(sub, subs, sbc)
323326
327+#define atomic64_add_return_relaxed atomic64_add_return_relaxed
328+#define atomic64_sub_return_relaxed atomic64_sub_return_relaxed
329+
330+#define atomic64_andnot atomic64_andnot
331+
332+ATOMIC64_OP(and, and, and)
333+ATOMIC64_OP(andnot, bic, bic)
334+ATOMIC64_OP(or, orr, orr)
335+ATOMIC64_OP(xor, eor, eor)
336+
324337 #undef ATOMIC64_OPS
325338 #undef ATOMIC64_OP_RETURN
326339 #undef ATOMIC64_OP
327340
328−static inline long long atomic64_cmpxchg(atomic64_t *ptr, long long old,
329− long long new)
341+static inline long long
342+atomic64_cmpxchg_relaxed(atomic64_t *ptr, long long old, long long new)
330343 {
331344 long long oldval;
332345 unsigned long res;
333346
334− smp_mb();
335347 prefetchw(&ptr->counter);
336348
337349 do {
@@ -346,17 +358,15 @@ static inline long long atomic64_cmpxchg(atomic64_t *ptr, long long old, · 8 unmodified lines
346358 : "cc");
347359 } while (res);
348360
349− smp_mb();
350−
351361 return oldval;
352362 }
363+#define atomic64_cmpxchg_relaxed atomic64_cmpxchg_relaxed
353364
354−static inline long long atomic64_xchg(atomic64_t *ptr, long long new)
365+static inline long long atomic64_xchg_relaxed(atomic64_t *ptr, long long new)
355366 {
356367 long long result;
357368 unsigned long tmp;
358369
359− smp_mb();
360370 prefetchw(&ptr->counter);
361371
362372 __asm__ __volatile__("@ atomic64_xchg\n"
@@ -368,10 +378,9 @@ static inline long long atomic64_xchg(atomic64_t *ptr, long long new) · 5 unmodified lines
368378 : "r" (&ptr->counter), "r" (new)
369379 : "cc");
370380
371− smp_mb();
372−
373381 return result;
374382 }
383+#define atomic64_xchg_relaxed atomic64_xchg_relaxed
375384
376385 static inline long long atomic64_dec_if_positive(atomic64_t *v)
377386 {
arch/arm/include/asm/barrier.h+2−2
@@ -67,12 +67,12 @@ · 66 unmodified lines
6767 do { \
6868 compiletime_assert_atomic_type(*p); \
6969 smp_mb(); \
70− ACCESS_ONCE(*p) = (v); \
70+ WRITE_ONCE(*p, v); \
7171 } while (0)
7272
7373 #define smp_load_acquire(p) \
7474 ({ \
75− typeof(*p) ___p1 = ACCESS_ONCE(*p); \
75+ typeof(*p) ___p1 = READ_ONCE(*p); \
7676 compiletime_assert_atomic_type(*p); \
7777 smp_mb(); \
7878 ___p1; \
arch/arm/include/asm/cmpxchg.h+8−39
@@ -35,7 +35,6 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size · 34 unmodified lines
3535 unsigned int tmp;
3636 #endif
3737
38− smp_mb();
3938 prefetchw((const void *)ptr);
4039
4140 switch (size) {
@@ -98,12 +97,11 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size · 56 unmodified lines
9897 __bad_xchg(ptr, size), ret = 0;
9998 break;
10099 }
101− smp_mb();
102100
103101 return ret;
104102 }
105103
106−#define xchg(ptr, x) ({ \
104+#define xchg_relaxed(ptr, x) ({ \
107105 (__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), \
108106 sizeof(*(ptr))); \
109107 })
@@ -117,6 +115,8 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size · 7 unmodified lines
117115 #error "SMP is not supported on this platform"
118116 #endif
119117
118+#define xchg xchg_relaxed
119+
120120 /*
121121 * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
122122 * them available.
@@ -194,23 +194,11 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, · 71 unmodified lines
194194 return oldval;
195195 }
196196
197−static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old,
198− unsigned long new, int size)
199−{
200− unsigned long ret;
201−
202− smp_mb();
203− ret = __cmpxchg(ptr, old, new, size);
204− smp_mb();
205−
206− return ret;
207−}
208−
209−#define cmpxchg(ptr,o,n) ({ \
210− (__typeof__(*(ptr)))__cmpxchg_mb((ptr), \
211− (unsigned long)(o), \
212− (unsigned long)(n), \
213− sizeof(*(ptr))); \
197+#define cmpxchg_relaxed(ptr,o,n) ({ \
198+ (__typeof__(*(ptr)))__cmpxchg((ptr), \
199+ (unsigned long)(o), \
200+ (unsigned long)(n), \
201+ sizeof(*(ptr))); \
214202 })
215203
216204 static inline unsigned long __cmpxchg_local(volatile void *ptr,
@@ -273,25 +261,6 @@ static inline unsigned long long __cmpxchg64(unsigned long long *ptr, · 56 unmodified lines
273261
274262 #define cmpxchg64_local(ptr, o, n) cmpxchg64_relaxed((ptr), (o), (n))
275263
276−static inline unsigned long long __cmpxchg64_mb(unsigned long long *ptr,
277− unsigned long long old,
278− unsigned long long new)
279−{
280− unsigned long long ret;
281−
282− smp_mb();
283− ret = __cmpxchg64(ptr, old, new);
284− smp_mb();
285−
286− return ret;
287−}
288−
289−#define cmpxchg64(ptr, o, n) ({ \
290− (__typeof__(*(ptr)))__cmpxchg64_mb((ptr), \
291− (unsigned long long)(o), \
292− (unsigned long long)(n)); \
293−})
294−
295264 #endif /* __LINUX_ARM_ARCH__ >= 6 */
296265
297266 #endif /* __ASM_ARM_CMPXCHG_H */
arch/arm/include/asm/jump_label.h+17−8
@@ -4,23 +4,32 @@ · 3 unmodified lines
44 #ifndef __ASSEMBLY__
55
66 #include <linux/types.h>
7+#include <asm/unified.h>
78
89 #define JUMP_LABEL_NOP_SIZE 4
910
10−#ifdef CONFIG_THUMB2_KERNEL
11−#define JUMP_LABEL_NOP "nop.w"
12−#else
13−#define JUMP_LABEL_NOP "nop"
14−#endif
11+static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
12+{
13+ asm_volatile_goto("1:\n\t"
14+ WASM(nop) "\n\t"
15+ ".pushsection __jump_table, \"aw\"\n\t"
16+ ".word 1b, %l[l_yes], %c0\n\t"
17+ ".popsection\n\t"
18+ : : "i" (&((char *)key)[branch]) : : l_yes);
19+
20+ return false;
21+l_yes:
22+ return true;
23+}
1524
16−static __always_inline bool arch_static_branch(struct static_key *key)
25+static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
1726 {
1827 asm_volatile_goto("1:\n\t"
19− JUMP_LABEL_NOP "\n\t"
28+ WASM(b) " %l[l_yes]\n\t"
2029 ".pushsection __jump_table, \"aw\"\n\t"
2130 ".word 1b, %l[l_yes], %c0\n\t"
2231 ".popsection\n\t"
23− : : "i" (key) : : l_yes);
32+ : : "i" (&((char *)key)[branch]) : : l_yes);
2433
2534 return false;
2635 l_yes:
arch/arm/kernel/jump_label.c+1−1
@@ -12,7 +12,7 @@ static void __arch_jump_label_transform(struct jump_entry *entry, · 11 unmodified lines
1212 void *addr = (void *)entry->code;
1313 unsigned int insn;
1414
15− if (type == JUMP_LABEL_ENABLE)
15+ if (type == JUMP_LABEL_JMP)
1616 insn = arm_gen_branch(entry->code, entry->target);
1717 else
1818 insn = arm_gen_nop();
arch/arm64/include/asm/atomic.h+14−0
@@ -85,6 +85,13 @@ static inline int atomic_##op##_return(int i, atomic_t *v) \ · 84 unmodified lines
8585 ATOMIC_OPS(add, add)
8686 ATOMIC_OPS(sub, sub)
8787
88+#define atomic_andnot atomic_andnot
89+
90+ATOMIC_OP(and, and)
91+ATOMIC_OP(andnot, bic)
92+ATOMIC_OP(or, orr)
93+ATOMIC_OP(xor, eor)
94+
8895 #undef ATOMIC_OPS
8996 #undef ATOMIC_OP_RETURN
9097 #undef ATOMIC_OP
@@ -183,6 +190,13 @@ static inline long atomic64_##op##_return(long i, atomic64_t *v) \ · 92 unmodified lines
183190 ATOMIC64_OPS(add, add)
184191 ATOMIC64_OPS(sub, sub)
185192
193+#define atomic64_andnot atomic64_andnot
194+
195+ATOMIC64_OP(and, and)
196+ATOMIC64_OP(andnot, bic)
197+ATOMIC64_OP(or, orr)
198+ATOMIC64_OP(xor, eor)
199+
186200 #undef ATOMIC64_OPS
187201 #undef ATOMIC64_OP_RETURN
188202 #undef ATOMIC64_OP
arch/arm64/include/asm/barrier.h+2−2
@@ -44,12 +44,12 @@ · 43 unmodified lines
4444 do { \
4545 compiletime_assert_atomic_type(*p); \
4646 barrier(); \
47− ACCESS_ONCE(*p) = (v); \
47+ WRITE_ONCE(*p, v); \
4848 } while (0)
4949
5050 #define smp_load_acquire(p) \
5151 ({ \
52− typeof(*p) ___p1 = ACCESS_ONCE(*p); \
52+ typeof(*p) ___p1 = READ_ONCE(*p); \
5353 compiletime_assert_atomic_type(*p); \
5454 barrier(); \
5555 ___p1; \
arch/arm64/include/asm/jump_label.h+16−2
@@ -26,14 +26,28 @@ · 25 unmodified lines
2626
2727 #define JUMP_LABEL_NOP_SIZE AARCH64_INSN_SIZE
2828
29−static __always_inline bool arch_static_branch(struct static_key *key)
29+static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
3030 {
3131 asm goto("1: nop\n\t"
3232 ".pushsection __jump_table, \"aw\"\n\t"
3333 ".align 3\n\t"
3434 ".quad 1b, %l[l_yes], %c0\n\t"
3535 ".popsection\n\t"
36− : : "i"(key) : : l_yes);
36+ : : "i"(&((char *)key)[branch]) : : l_yes);
37+
38+ return false;
39+l_yes:
40+ return true;
41+}
42+
43+static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
44+{
45+ asm goto("1: b %l[l_yes]\n\t"
46+ ".pushsection __jump_table, \"aw\"\n\t"
47+ ".align 3\n\t"
48+ ".quad 1b, %l[l_yes], %c0\n\t"
49+ ".popsection\n\t"
50+ : : "i"(&((char *)key)[branch]) : : l_yes);
3751
3852 return false;
3953 l_yes:
arch/arm64/kernel/jump_label.c+1−1
@@ -28,7 +28,7 @@ void arch_jump_label_transform(struct jump_entry *entry, · 27 unmodified lines
2828 void *addr = (void *)entry->code;
2929 u32 insn;
3030
31− if (type == JUMP_LABEL_ENABLE) {
31+ if (type == JUMP_LABEL_JMP) {
3232 insn = aarch64_insn_gen_branch_imm(entry->code,
3333 entry->target,
3434 AARCH64_INSN_BRANCH_NOLINK);
arch/avr32/include/asm/atomic.h+12−0
@@ -44,6 +44,18 @@ static inline int __atomic_##op##_return(int i, atomic_t *v) \ · 43 unmodified lines
4444 ATOMIC_OP_RETURN(sub, sub, rKs21)
4545 ATOMIC_OP_RETURN(add, add, r)
4646
47+#define ATOMIC_OP(op, asm_op) \
48+ATOMIC_OP_RETURN(op, asm_op, r) \
49+static inline void atomic_##op(int i, atomic_t *v) \
50+{ \
51+ (void)__atomic_##op##_return(i, v); \
52+}
53+
54+ATOMIC_OP(and, and)
55+ATOMIC_OP(or, or)
56+ATOMIC_OP(xor, eor)
57+
58+#undef ATOMIC_OP
4759 #undef ATOMIC_OP_RETURN
4860
4961 /*
arch/blackfin/include/asm/atomic.h+9−7
@@ -16,19 +16,21 @@ · 15 unmodified lines
1616 #include <linux/types.h>
1717
1818 asmlinkage int __raw_uncached_fetch_asm(const volatile int *ptr);
19−asmlinkage int __raw_atomic_update_asm(volatile int *ptr, int value);
20−asmlinkage int __raw_atomic_clear_asm(volatile int *ptr, int value);
21−asmlinkage int __raw_atomic_set_asm(volatile int *ptr, int value);
19+asmlinkage int __raw_atomic_add_asm(volatile int *ptr, int value);
20+
21+asmlinkage int __raw_atomic_and_asm(volatile int *ptr, int value);
22+asmlinkage int __raw_atomic_or_asm(volatile int *ptr, int value);
2223 asmlinkage int __raw_atomic_xor_asm(volatile int *ptr, int value);
2324 asmlinkage int __raw_atomic_test_asm(const volatile int *ptr, int value);
2425
2526 #define atomic_read(v) __raw_uncached_fetch_asm(&(v)->counter)
2627
27−#define atomic_add_return(i, v) __raw_atomic_update_asm(&(v)->counter, i)
28−#define atomic_sub_return(i, v) __raw_atomic_update_asm(&(v)->counter, -(i))
28+#define atomic_add_return(i, v) __raw_atomic_add_asm(&(v)->counter, i)
29+#define atomic_sub_return(i, v) __raw_atomic_add_asm(&(v)->counter, -(i))
2930
30−#define atomic_clear_mask(m, v) __raw_atomic_clear_asm(&(v)->counter, m)
31−#define atomic_set_mask(m, v) __raw_atomic_set_asm(&(v)->counter, m)
31+#define atomic_or(i, v) (void)__raw_atomic_or_asm(&(v)->counter, i)
32+#define atomic_and(i, v) (void)__raw_atomic_and_asm(&(v)->counter, i)
33+#define atomic_xor(i, v) (void)__raw_atomic_xor_asm(&(v)->counter, i)
3234
3335 #endif
3436
arch/blackfin/kernel/bfin_ksyms.c+4−3
@@ -83,11 +83,12 @@ EXPORT_SYMBOL(insl); · 82 unmodified lines
8383 EXPORT_SYMBOL(insl_16);
8484
8585 #ifdef CONFIG_SMP
86−EXPORT_SYMBOL(__raw_atomic_update_asm);
87−EXPORT_SYMBOL(__raw_atomic_clear_asm);
88−EXPORT_SYMBOL(__raw_atomic_set_asm);
86+EXPORT_SYMBOL(__raw_atomic_add_asm);
87+EXPORT_SYMBOL(__raw_atomic_and_asm);
88+EXPORT_SYMBOL(__raw_atomic_or_asm);
8989 EXPORT_SYMBOL(__raw_atomic_xor_asm);
9090 EXPORT_SYMBOL(__raw_atomic_test_asm);
91+
9192 EXPORT_SYMBOL(__raw_xchg_1_asm);
9293 EXPORT_SYMBOL(__raw_xchg_2_asm);
9394 EXPORT_SYMBOL(__raw_xchg_4_asm);
arch/blackfin/mach-bf561/atomic.S+15−15
@@ -587,10 +587,10 @@ ENDPROC(___raw_write_unlock_asm) · 586 unmodified lines
587587 * r0 = ptr
588588 * r1 = value
589589 *
590− * Add a signed value to a 32bit word and return the new value atomically.
590+ * ADD a signed value to a 32bit word and return the new value atomically.
591591 * Clobbers: r3:0, p1:0
592592 */
593−ENTRY(___raw_atomic_update_asm)
593+ENTRY(___raw_atomic_add_asm)
594594 p1 = r0;
595595 r3 = r1;
596596 [--sp] = rets;
@@ -603,19 +603,19 @@ ENTRY(___raw_atomic_update_asm) · 6 unmodified lines
603603 r0 = r3;
604604 rets = [sp++];
605605 rts;
606−ENDPROC(___raw_atomic_update_asm)
606+ENDPROC(___raw_atomic_add_asm)
607607
608608 /*
609609 * r0 = ptr
610610 * r1 = mask
611611 *
612− * Clear the mask bits from a 32bit word and return the old 32bit value
612+ * AND the mask bits from a 32bit word and return the old 32bit value
613613 * atomically.
614614 * Clobbers: r3:0, p1:0
615615 */
616−ENTRY(___raw_atomic_clear_asm)
616+ENTRY(___raw_atomic_and_asm)
617617 p1 = r0;
618− r3 = ~r1;
618+ r3 = r1;
619619 [--sp] = rets;
620620 call _get_core_lock;
621621 r2 = [p1];
@@ -627,17 +627,17 @@ ENTRY(___raw_atomic_clear_asm) · 5 unmodified lines
627627 r0 = r3;
628628 rets = [sp++];
629629 rts;
630−ENDPROC(___raw_atomic_clear_asm)
630+ENDPROC(___raw_atomic_and_asm)
631631
632632 /*
633633 * r0 = ptr
634634 * r1 = mask
635635 *
636− * Set the mask bits into a 32bit word and return the old 32bit value
636+ * OR the mask bits into a 32bit word and return the old 32bit value
637637 * atomically.
638638 * Clobbers: r3:0, p1:0
639639 */
640−ENTRY(___raw_atomic_set_asm)
640+ENTRY(___raw_atomic_or_asm)
641641 p1 = r0;
642642 r3 = r1;
643643 [--sp] = rets;
@@ -651,7 +651,7 @@ ENTRY(___raw_atomic_set_asm) · 7 unmodified lines
651651 r0 = r3;
652652 rets = [sp++];
653653 rts;
654−ENDPROC(___raw_atomic_set_asm)
654+ENDPROC(___raw_atomic_or_asm)
655655
656656 /*
657657 * r0 = ptr
@@ -787,7 +787,7 @@ ENTRY(___raw_bit_set_asm) · 129 unmodified lines
787787 r2 = r1;
788788 r1 = 1;
789789 r1 <<= r2;
790− jump ___raw_atomic_set_asm
790+ jump ___raw_atomic_or_asm
791791 ENDPROC(___raw_bit_set_asm)
792792
793793 /*
@@ -798,10 +798,10 @@ ENDPROC(___raw_bit_set_asm) · 4 unmodified lines
798798 * Clobbers: r3:0, p1:0
799799 */
800800 ENTRY(___raw_bit_clear_asm)
801− r2 = r1;
802− r1 = 1;
803− r1 <<= r2;
804− jump ___raw_atomic_clear_asm
801+ r2 = 1;
802+ r2 <<= r1;
803+ r1 = ~r2;
804+ jump ___raw_atomic_and_asm
805805 ENDPROC(___raw_bit_clear_asm)
806806
807807 /*
arch/blackfin/mach-common/smp.c+1−1
@@ -195,7 +195,7 @@ void send_ipi(const struct cpumask *cpumask, enum ipi_message_type msg) · 194 unmodified lines
195195 local_irq_save(flags);
196196 for_each_cpu(cpu, cpumask) {
197197 bfin_ipi_data = &per_cpu(bfin_ipi, cpu);
198− atomic_set_mask((1 << msg), &bfin_ipi_data->bits);
198+ atomic_or((1 << msg), &bfin_ipi_data->bits);
199199 atomic_inc(&bfin_ipi_data->count);
200200 }
201201 local_irq_restore(flags);
arch/frv/include/asm/atomic.h+54−53
@@ -15,7 +15,6 @@ · 14 unmodified lines
1515 #define _ASM_ATOMIC_H
1616
1717 #include <linux/types.h>
18−#include <asm/spr-regs.h>
1918 #include <asm/cmpxchg.h>
2019 #include <asm/barrier.h>
2120
@@ -23,6 +22,8 @@ · 1 unmodified line
2322 #error not SMP safe
2423 #endif
2524
25+#include <asm/atomic_defs.h>
26+
2627 /*
2728 * Atomic operations that C can't guarantee us. Useful for
2829 * resource counting etc..
@@ -34,56 +35,26 @@ · 5 unmodified lines
3435 #define atomic_read(v) ACCESS_ONCE((v)->counter)
3536 #define atomic_set(v, i) (((v)->counter) = (i))
3637
37−#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
38−static inline int atomic_add_return(int i, atomic_t *v)
38+static inline int atomic_inc_return(atomic_t *v)
3939 {
40− unsigned long val;
40+ return __atomic_add_return(1, &v->counter);
41+}
4142
42− asm("0: \n"
43− " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */
44− " ckeq icc3,cc7 \n"
45− " ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */
46− " orcr cc7,cc7,cc3 \n" /* set CC3 to true */
47− " add%I2 %1,%2,%1 \n"
48− " cst.p %1,%M0 ,cc3,#1 \n"
49− " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */
50− " beq icc3,#0,0b \n"
51− : "+U"(v->counter), "=&r"(val)
52− : "NPr"(i)
53− : "memory", "cc7", "cc3", "icc3"
54− );
43+static inline int atomic_dec_return(atomic_t *v)
44+{
45+ return __atomic_sub_return(1, &v->counter);
46+}
5547
56− return val;
48+static inline int atomic_add_return(int i, atomic_t *v)
49+{
50+ return __atomic_add_return(i, &v->counter);
5751 }
5852
5953 static inline int atomic_sub_return(int i, atomic_t *v)
6054 {
61− unsigned long val;
62−
63− asm("0: \n"
64− " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */
65− " ckeq icc3,cc7 \n"
66− " ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */
67− " orcr cc7,cc7,cc3 \n" /* set CC3 to true */
68− " sub%I2 %1,%2,%1 \n"
69− " cst.p %1,%M0 ,cc3,#1 \n"
70− " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */
71− " beq icc3,#0,0b \n"
72− : "+U"(v->counter), "=&r"(val)
73− : "NPr"(i)
74− : "memory", "cc7", "cc3", "icc3"
75− );
76−
77− return val;
55+ return __atomic_sub_return(i, &v->counter);
7856 }
7957
80−#else
81−
82−extern int atomic_add_return(int i, atomic_t *v);
83−extern int atomic_sub_return(int i, atomic_t *v);
84−
85−#endif
86−
8758 static inline int atomic_add_negative(int i, atomic_t *v)
8859 {
8960 return atomic_add_return(i, v) < 0;
@@ -101,17 +72,14 @@ static inline void atomic_sub(int i, atomic_t *v) · 11 unmodified lines
10172
10273 static inline void atomic_inc(atomic_t *v)
10374 {
104− atomic_add_return(1, v);
75+ atomic_inc_return(v);
10576 }
10677
10778 static inline void atomic_dec(atomic_t *v)
10879 {
109− atomic_sub_return(1, v);
80+ atomic_dec_return(v);
11081 }
11182
112−#define atomic_dec_return(v) atomic_sub_return(1, (v))
113−#define atomic_inc_return(v) atomic_add_return(1, (v))
114−
11583 #define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
11684 #define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
11785 #define atomic_inc_and_test(v) (atomic_add_return(1, (v)) == 0)
@@ -120,18 +88,19 @@ static inline void atomic_dec(atomic_t *v) · 2 unmodified lines
12088 * 64-bit atomic ops
12189 */
12290 typedef struct {
123− volatile long long counter;
91+ long long counter;
12492 } atomic64_t;
12593
12694 #define ATOMIC64_INIT(i) { (i) }
12795
128−static inline long long atomic64_read(atomic64_t *v)
96+static inline long long atomic64_read(const atomic64_t *v)
12997 {
13098 long long counter;
13199
132100 asm("ldd%I1 %M1,%0"
133101 : "=e"(counter)
134102 : "m"(v->counter));
103+
135104 return counter;
136105 }
137106
@@ -142,10 +111,25 @@ static inline void atomic64_set(atomic64_t *v, long long i) · 4 unmodified lines
142111 : "e"(i));
143112 }
144113
145−extern long long atomic64_inc_return(atomic64_t *v);
146−extern long long atomic64_dec_return(atomic64_t *v);
147−extern long long atomic64_add_return(long long i, atomic64_t *v);
148−extern long long atomic64_sub_return(long long i, atomic64_t *v);
114+static inline long long atomic64_inc_return(atomic64_t *v)
115+{
116+ return __atomic64_add_return(1, &v->counter);
117+}
118+
119+static inline long long atomic64_dec_return(atomic64_t *v)
120+{
121+ return __atomic64_sub_return(1, &v->counter);
122+}
123+
124+static inline long long atomic64_add_return(long long i, atomic64_t *v)
125+{
126+ return __atomic64_add_return(i, &v->counter);
127+}
128+
129+static inline long long atomic64_sub_return(long long i, atomic64_t *v)
130+{
131+ return __atomic64_sub_return(i, &v->counter);
132+}
149133
150134 static inline long long atomic64_add_negative(long long i, atomic64_t *v)
151135 {
@@ -176,6 +160,7 @@ static inline void atomic64_dec(atomic64_t *v) · 24 unmodified lines
176160 #define atomic64_dec_and_test(v) (atomic64_dec_return((v)) == 0)
177161 #define atomic64_inc_and_test(v) (atomic64_inc_return((v)) == 0)
178162
163+
179164 #define atomic_cmpxchg(v, old, new) (cmpxchg(&(v)->counter, old, new))
180165 #define atomic_xchg(v, new) (xchg(&(v)->counter, new))
181166 #define atomic64_cmpxchg(v, old, new) (__cmpxchg_64(old, new, &(v)->counter))
@@ -196,5 +181,21 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) · 14 unmodified lines
196181 return c;
197182 }
198183
184+#define ATOMIC_OP(op) \
185+static inline void atomic_##op(int i, atomic_t *v) \
186+{ \
187+ (void)__atomic32_fetch_##op(i, &v->counter); \
188+} \
189+ \
190+static inline void atomic64_##op(long long i, atomic64_t *v) \
191+{ \
192+ (void)__atomic64_fetch_##op(i, &v->counter); \
193+}
194+
195+ATOMIC_OP(or)
196+ATOMIC_OP(and)
197+ATOMIC_OP(xor)
198+
199+#undef ATOMIC_OP
199200
200201 #endif /* _ASM_ATOMIC_H */
arch/frv/include/asm/atomic_defs.h+172−0
@@ -0,0 +1,172 @@
1+
2+#include <asm/spr-regs.h>
3+
4+#ifdef __ATOMIC_LIB__
5+
6+#ifdef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
7+
8+#define ATOMIC_QUALS
9+#define ATOMIC_EXPORT(x) EXPORT_SYMBOL(x)
10+
11+#else /* !OUTOFLINE && LIB */
12+
13+#define ATOMIC_OP_RETURN(op)
14+#define ATOMIC_FETCH_OP(op)
15+
16+#endif /* OUTOFLINE */
17+
18+#else /* !__ATOMIC_LIB__ */
19+
20+#define ATOMIC_EXPORT(x)
21+
22+#ifdef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
23+
24+#define ATOMIC_OP_RETURN(op) \
25+extern int __atomic_##op##_return(int i, int *v); \
26+extern long long __atomic64_##op##_return(long long i, long long *v);
27+
28+#define ATOMIC_FETCH_OP(op) \
29+extern int __atomic32_fetch_##op(int i, int *v); \
30+extern long long __atomic64_fetch_##op(long long i, long long *v);
31+
32+#else /* !OUTOFLINE && !LIB */
33+
34+#define ATOMIC_QUALS static inline
35+
36+#endif /* OUTOFLINE */
37+#endif /* __ATOMIC_LIB__ */
38+
39+
40+/*
41+ * Note on the 64 bit inline asm variants...
42+ *
43+ * CSTD is a conditional instruction and needs a constrained memory reference.
44+ * Normally 'U' provides the correct constraints for conditional instructions
45+ * and this is used for the 32 bit version, however 'U' does not appear to work
46+ * for 64 bit values (gcc-4.9)
47+ *
48+ * The exact constraint is that conditional instructions cannot deal with an
49+ * immediate displacement in the memory reference, so what we do is we read the
50+ * address through a volatile cast into a local variable in order to insure we
51+ * _have_ to compute the correct address without displacement. This allows us
52+ * to use the regular 'm' for the memory address.
53+ *
54+ * Furthermore, the %Ln operand, which prints the low word register (r+1),
55+ * really only works for registers, this means we cannot allow immediate values
56+ * for the 64 bit versions -- like we do for the 32 bit ones.
57+ *
58+ */
59+
60+#ifndef ATOMIC_OP_RETURN
61+#define ATOMIC_OP_RETURN(op) \
62+ATOMIC_QUALS int __atomic_##op##_return(int i, int *v) \
63+{ \
64+ int val; \
65+ \
66+ asm volatile( \
67+ "0: \n" \
68+ " orcc gr0,gr0,gr0,icc3 \n" \
69+ " ckeq icc3,cc7 \n" \
70+ " ld.p %M0,%1 \n" \
71+ " orcr cc7,cc7,cc3 \n" \
72+ " "#op"%I2 %1,%2,%1 \n" \
73+ " cst.p %1,%M0 ,cc3,#1 \n" \
74+ " corcc gr29,gr29,gr0 ,cc3,#1 \n" \
75+ " beq icc3,#0,0b \n" \
76+ : "+U"(*v), "=&r"(val) \
77+ : "NPr"(i) \
78+ : "memory", "cc7", "cc3", "icc3" \
79+ ); \
80+ \
81+ return val; \
82+} \
83+ATOMIC_EXPORT(__atomic_##op##_return); \
84+ \
85+ATOMIC_QUALS long long __atomic64_##op##_return(long long i, long long *v) \
86+{ \
87+ long long *__v = READ_ONCE(v); \
88+ long long val; \
89+ \
90+ asm volatile( \
91+ "0: \n" \
92+ " orcc gr0,gr0,gr0,icc3 \n" \
93+ " ckeq icc3,cc7 \n" \
94+ " ldd.p %M0,%1 \n" \
95+ " orcr cc7,cc7,cc3 \n" \
96+ " "#op"cc %L1,%L2,%L1,icc0 \n" \
97+ " "#op"x %1,%2,%1,icc0 \n" \
98+ " cstd.p %1,%M0 ,cc3,#1 \n" \
99+ " corcc gr29,gr29,gr0 ,cc3,#1 \n" \
100+ " beq icc3,#0,0b \n" \
101+ : "+m"(*__v), "=&e"(val) \
102+ : "e"(i) \
103+ : "memory", "cc7", "cc3", "icc0", "icc3" \
104+ ); \
105+ \
106+ return val; \
107+} \
108+ATOMIC_EXPORT(__atomic64_##op##_return);
109+#endif
110+
111+#ifndef ATOMIC_FETCH_OP
112+#define ATOMIC_FETCH_OP(op) \
113+ATOMIC_QUALS int __atomic32_fetch_##op(int i, int *v) \
114+{ \
115+ int old, tmp; \
116+ \
117+ asm volatile( \
118+ "0: \n" \
119+ " orcc gr0,gr0,gr0,icc3 \n" \
120+ " ckeq icc3,cc7 \n" \
121+ " ld.p %M0,%1 \n" \
122+ " orcr cc7,cc7,cc3 \n" \
123+ " "#op"%I3 %1,%3,%2 \n" \
124+ " cst.p %2,%M0 ,cc3,#1 \n" \
125+ " corcc gr29,gr29,gr0 ,cc3,#1 \n" \
126+ " beq icc3,#0,0b \n" \
127+ : "+U"(*v), "=&r"(old), "=r"(tmp) \
128+ : "NPr"(i) \
129+ : "memory", "cc7", "cc3", "icc3" \
130+ ); \
131+ \
132+ return old; \
133+} \
134+ATOMIC_EXPORT(__atomic32_fetch_##op); \
135+ \
136+ATOMIC_QUALS long long __atomic64_fetch_##op(long long i, long long *v) \
137+{ \
138+ long long *__v = READ_ONCE(v); \
139+ long long old, tmp; \
140+ \
141+ asm volatile( \
142+ "0: \n" \
143+ " orcc gr0,gr0,gr0,icc3 \n" \
144+ " ckeq icc3,cc7 \n" \
145+ " ldd.p %M0,%1 \n" \
146+ " orcr cc7,cc7,cc3 \n" \
147+ " "#op" %L1,%L3,%L2 \n" \
148+ " "#op" %1,%3,%2 \n" \
149+ " cstd.p %2,%M0 ,cc3,#1 \n" \
150+ " corcc gr29,gr29,gr0 ,cc3,#1 \n" \
151+ " beq icc3,#0,0b \n" \
152+ : "+m"(*__v), "=&e"(old), "=e"(tmp) \
153+ : "e"(i) \
154+ : "memory", "cc7", "cc3", "icc3" \
155+ ); \
156+ \
157+ return old; \
158+} \
159+ATOMIC_EXPORT(__atomic64_fetch_##op);
160+#endif
161+
162+ATOMIC_FETCH_OP(or)
163+ATOMIC_FETCH_OP(and)
164+ATOMIC_FETCH_OP(xor)
165+
166+ATOMIC_OP_RETURN(add)
167+ATOMIC_OP_RETURN(sub)
168+
169+#undef ATOMIC_FETCH_OP
170+#undef ATOMIC_OP_RETURN
171+#undef ATOMIC_QUALS
172+#undef ATOMIC_EXPORT
arch/frv/include/asm/bitops.h+10−89
@@ -25,109 +25,30 @@ · 24 unmodified lines
2525
2626 #include <asm-generic/bitops/ffz.h>
2727
28−#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
29−static inline
30−unsigned long atomic_test_and_ANDNOT_mask(unsigned long mask, volatile unsigned long *v)
31−{
32− unsigned long old, tmp;
33−
34− asm volatile(
35− "0: \n"
36− " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */
37− " ckeq icc3,cc7 \n"
38− " ld.p %M0,%1 \n" /* LD.P/ORCR are atomic */
39− " orcr cc7,cc7,cc3 \n" /* set CC3 to true */
40− " and%I3 %1,%3,%2 \n"
41− " cst.p %2,%M0 ,cc3,#1 \n" /* if store happens... */
42− " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* ... clear ICC3.Z */
43− " beq icc3,#0,0b \n"
44− : "+U"(*v), "=&r"(old), "=r"(tmp)
45− : "NPr"(~mask)
46− : "memory", "cc7", "cc3", "icc3"
47− );
48−
49− return old;
50−}
51−
52−static inline
53−unsigned long atomic_test_and_OR_mask(unsigned long mask, volatile unsigned long *v)
54−{
55− unsigned long old, tmp;
56−
57− asm volatile(
58− "0: \n"
59− " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */
60− " ckeq icc3,cc7 \n"
61− " ld.p %M0,%1 \n" /* LD.P/ORCR are atomic */
62− " orcr cc7,cc7,cc3 \n" /* set CC3 to true */
63− " or%I3 %1,%3,%2 \n"
64− " cst.p %2,%M0 ,cc3,#1 \n" /* if store happens... */
65− " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* ... clear ICC3.Z */
66− " beq icc3,#0,0b \n"
67− : "+U"(*v), "=&r"(old), "=r"(tmp)
68− : "NPr"(mask)
69− : "memory", "cc7", "cc3", "icc3"
70− );
71−
72− return old;
73−}
74−
75−static inline
76−unsigned long atomic_test_and_XOR_mask(unsigned long mask, volatile unsigned long *v)
77−{
78− unsigned long old, tmp;
79−
80− asm volatile(
81− "0: \n"
82− " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */
83− " ckeq icc3,cc7 \n"
84− " ld.p %M0,%1 \n" /* LD.P/ORCR are atomic */
85− " orcr cc7,cc7,cc3 \n" /* set CC3 to true */
86− " xor%I3 %1,%3,%2 \n"
87− " cst.p %2,%M0 ,cc3,#1 \n" /* if store happens... */
88− " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* ... clear ICC3.Z */
89− " beq icc3,#0,0b \n"
90− : "+U"(*v), "=&r"(old), "=r"(tmp)
91− : "NPr"(mask)
92− : "memory", "cc7", "cc3", "icc3"
93− );
94−
95− return old;
96−}
97−
98−#else
99−
100−extern unsigned long atomic_test_and_ANDNOT_mask(unsigned long mask, volatile unsigned long *v);
101−extern unsigned long atomic_test_and_OR_mask(unsigned long mask, volatile unsigned long *v);
102−extern unsigned long atomic_test_and_XOR_mask(unsigned long mask, volatile unsigned long *v);
103−
104−#endif
105−
106−#define atomic_clear_mask(mask, v) atomic_test_and_ANDNOT_mask((mask), (v))
107−#define atomic_set_mask(mask, v) atomic_test_and_OR_mask((mask), (v))
28+#include <asm/atomic.h>
10829
10930 static inline int test_and_clear_bit(unsigned long nr, volatile void *addr)
11031 {
111− volatile unsigned long *ptr = addr;
112− unsigned long mask = 1UL << (nr & 31);
32+ unsigned int *ptr = (void *)addr;
33+ unsigned int mask = 1UL << (nr & 31);
11334 ptr += nr >> 5;
114− return (atomic_test_and_ANDNOT_mask(mask, ptr) & mask) != 0;
35+ return (__atomic32_fetch_and(~mask, ptr) & mask) != 0;
11536 }
11637
11738 static inline int test_and_set_bit(unsigned long nr, volatile void *addr)
11839 {
119− volatile unsigned long *ptr = addr;
120− unsigned long mask = 1UL << (nr & 31);
40+ unsigned int *ptr = (void *)addr;
41+ unsigned int mask = 1UL << (nr & 31);
12142 ptr += nr >> 5;
122− return (atomic_test_and_OR_mask(mask, ptr) & mask) != 0;
43+ return (__atomic32_fetch_or(mask, ptr) & mask) != 0;
12344 }
12445
12546 static inline int test_and_change_bit(unsigned long nr, volatile void *addr)
12647 {
127− volatile unsigned long *ptr = addr;
128− unsigned long mask = 1UL << (nr & 31);
48+ unsigned int *ptr = (void *)addr;
49+ unsigned int mask = 1UL << (nr & 31);
12950 ptr += nr >> 5;
130− return (atomic_test_and_XOR_mask(mask, ptr) & mask) != 0;
51+ return (__atomic32_fetch_xor(mask, ptr) & mask) != 0;
13152 }
13253
13354 static inline void clear_bit(unsigned long nr, volatile void *addr)
arch/frv/kernel/dma.c+3−3
@@ -109,13 +109,13 @@ static struct frv_dma_channel frv_dma_channels[FRV_DMA_NCHANS] = { · 108 unmodified lines
109109
110110 static DEFINE_RWLOCK(frv_dma_channels_lock);
111111
112−unsigned long frv_dma_inprogress;
112+unsigned int frv_dma_inprogress;
113113
114114 #define frv_clear_dma_inprogress(channel) \
115− atomic_clear_mask(1 << (channel), &frv_dma_inprogress);
115+ (void)__atomic32_fetch_and(~(1 << (channel)), &frv_dma_inprogress);
116116
117117 #define frv_set_dma_inprogress(channel) \
118− atomic_set_mask(1 << (channel), &frv_dma_inprogress);
118+ (void)__atomic32_fetch_or(1 << (channel), &frv_dma_inprogress);
119119
120120 /*****************************************************************************/
121121 /*
arch/frv/kernel/frv_ksyms.c+0−5
@@ -58,11 +58,6 @@ EXPORT_SYMBOL(__outsl_ns); · 57 unmodified lines
5858 EXPORT_SYMBOL(__insl_ns);
5959
6060 #ifdef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
61−EXPORT_SYMBOL(atomic_test_and_ANDNOT_mask);
62−EXPORT_SYMBOL(atomic_test_and_OR_mask);
63−EXPORT_SYMBOL(atomic_test_and_XOR_mask);
64−EXPORT_SYMBOL(atomic_add_return);
65−EXPORT_SYMBOL(atomic_sub_return);
6661 EXPORT_SYMBOL(__xchg_32);
6762 EXPORT_SYMBOL(__cmpxchg_32);
6863 #endif
arch/frv/lib/Makefile+1−1
@@ -5,4 +5,4 @@ · 4 unmodified lines
55 lib-y := \
66 __ashldi3.o __lshrdi3.o __muldi3.o __ashrdi3.o __negdi2.o __ucmpdi2.o \
77 checksum.o memcpy.o memset.o atomic-ops.o atomic64-ops.o \
8− outsl_ns.o outsl_sw.o insl_ns.o insl_sw.o cache.o
8+ outsl_ns.o outsl_sw.o insl_ns.o insl_sw.o cache.o atomic-lib.o
arch/frv/lib/atomic-lib.c+7−0
@@ -0,0 +1,7 @@
1+
2+#include <linux/export.h>
3+#include <asm/atomic.h>
4+
5+#define __ATOMIC_LIB__
6+
7+#include <asm/atomic_defs.h>
arch/frv/lib/atomic-ops.S+0−110
@@ -17,116 +17,6 @@ · 16 unmodified lines
1717 .text
1818 .balign 4
1919
20−###############################################################################
21−#
22−# unsigned long atomic_test_and_ANDNOT_mask(unsigned long mask, volatile unsigned long *v);
23−#
24−###############################################################################
25− .globl atomic_test_and_ANDNOT_mask
26− .type atomic_test_and_ANDNOT_mask,@function
27−atomic_test_and_ANDNOT_mask:
28− not.p gr8,gr10
29−0:
30− orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */
31− ckeq icc3,cc7
32− ld.p @(gr9,gr0),gr8 /* LD.P/ORCR must be atomic */
33− orcr cc7,cc7,cc3 /* set CC3 to true */
34− and gr8,gr10,gr11
35− cst.p gr11,@(gr9,gr0) ,cc3,#1
36− corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */
37− beq icc3,#0,0b
38− bralr
39−
40− .size atomic_test_and_ANDNOT_mask, .-atomic_test_and_ANDNOT_mask
41−
42−###############################################################################
43−#
44−# unsigned long atomic_test_and_OR_mask(unsigned long mask, volatile unsigned long *v);
45−#
46−###############################################################################
47− .globl atomic_test_and_OR_mask
48− .type atomic_test_and_OR_mask,@function
49−atomic_test_and_OR_mask:
50− or.p gr8,gr8,gr10
51−0:
52− orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */
53− ckeq icc3,cc7
54− ld.p @(gr9,gr0),gr8 /* LD.P/ORCR must be atomic */
55− orcr cc7,cc7,cc3 /* set CC3 to true */
56− or gr8,gr10,gr11
57− cst.p gr11,@(gr9,gr0) ,cc3,#1
58− corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */
59− beq icc3,#0,0b
60− bralr
61−
62− .size atomic_test_and_OR_mask, .-atomic_test_and_OR_mask
63−
64−###############################################################################
65−#
66−# unsigned long atomic_test_and_XOR_mask(unsigned long mask, volatile unsigned long *v);
67−#
68−###############################################################################
69− .globl atomic_test_and_XOR_mask
70− .type atomic_test_and_XOR_mask,@function
71−atomic_test_and_XOR_mask:
72− or.p gr8,gr8,gr10
73−0:
74− orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */
75− ckeq icc3,cc7
76− ld.p @(gr9,gr0),gr8 /* LD.P/ORCR must be atomic */
77− orcr cc7,cc7,cc3 /* set CC3 to true */
78− xor gr8,gr10,gr11
79− cst.p gr11,@(gr9,gr0) ,cc3,#1
80− corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */
81− beq icc3,#0,0b
82− bralr
83−
84− .size atomic_test_and_XOR_mask, .-atomic_test_and_XOR_mask
85−
86−###############################################################################
87−#
88−# int atomic_add_return(int i, atomic_t *v)
89−#
90−###############################################################################
91− .globl atomic_add_return
92− .type atomic_add_return,@function
93−atomic_add_return:
94− or.p gr8,gr8,gr10
95−0:
96− orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */
97− ckeq icc3,cc7
98− ld.p @(gr9,gr0),gr8 /* LD.P/ORCR must be atomic */
99− orcr cc7,cc7,cc3 /* set CC3 to true */
100− add gr8,gr10,gr8
101− cst.p gr8,@(gr9,gr0) ,cc3,#1
102− corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */
103− beq icc3,#0,0b
104− bralr
105−
106− .size atomic_add_return, .-atomic_add_return
107−
108−###############################################################################
109−#
110−# int atomic_sub_return(int i, atomic_t *v)
111−#
112−###############################################################################
113− .globl atomic_sub_return
114− .type atomic_sub_return,@function
115−atomic_sub_return:
116− or.p gr8,gr8,gr10
117−0:
118− orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */
119− ckeq icc3,cc7
120− ld.p @(gr9,gr0),gr8 /* LD.P/ORCR must be atomic */
121− orcr cc7,cc7,cc3 /* set CC3 to true */
122− sub gr8,gr10,gr8
123− cst.p gr8,@(gr9,gr0) ,cc3,#1
124− corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */
125− beq icc3,#0,0b
126− bralr
127−
128− .size atomic_sub_return, .-atomic_sub_return
129−
13020 ###############################################################################
13121 #
13222 # uint32_t __xchg_32(uint32_t i, uint32_t *v)
arch/frv/lib/atomic64-ops.S+0−94
@@ -18,100 +18,6 @@ · 17 unmodified lines
1818 .balign 4
1919
2020
21−###############################################################################
22−#
23−# long long atomic64_inc_return(atomic64_t *v)
24−#
25−###############################################################################
26− .globl atomic64_inc_return
27− .type atomic64_inc_return,@function
28−atomic64_inc_return:
29− or.p gr8,gr8,gr10
30−0:
31− orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */
32− ckeq icc3,cc7
33− ldd.p @(gr10,gr0),gr8 /* LDD.P/ORCR must be atomic */
34− orcr cc7,cc7,cc3 /* set CC3 to true */
35− addicc gr9,#1,gr9,icc0
36− addxi gr8,#0,gr8,icc0
37− cstd.p gr8,@(gr10,gr0) ,cc3,#1
38− corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */
39− beq icc3,#0,0b
40− bralr
41−
42− .size atomic64_inc_return, .-atomic64_inc_return
43−
44−###############################################################################
45−#
46−# long long atomic64_dec_return(atomic64_t *v)
47−#
48−###############################################################################
49− .globl atomic64_dec_return
50− .type atomic64_dec_return,@function
51−atomic64_dec_return:
52− or.p gr8,gr8,gr10
53−0:
54− orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */
55− ckeq icc3,cc7
56− ldd.p @(gr10,gr0),gr8 /* LDD.P/ORCR must be atomic */
57− orcr cc7,cc7,cc3 /* set CC3 to true */
58− subicc gr9,#1,gr9,icc0
59− subxi gr8,#0,gr8,icc0
60− cstd.p gr8,@(gr10,gr0) ,cc3,#1
61− corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */
62− beq icc3,#0,0b
63− bralr
64−
65− .size atomic64_dec_return, .-atomic64_dec_return
66−
67−###############################################################################
68−#
69−# long long atomic64_add_return(long long i, atomic64_t *v)
70−#
71−###############################################################################
72− .globl atomic64_add_return
73− .type atomic64_add_return,@function
74−atomic64_add_return:
75− or.p gr8,gr8,gr4
76− or gr9,gr9,gr5
77−0:
78− orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */
79− ckeq icc3,cc7
80− ldd.p @(gr10,gr0),gr8 /* LDD.P/ORCR must be atomic */
81− orcr cc7,cc7,cc3 /* set CC3 to true */
82− addcc gr9,gr5,gr9,icc0
83− addx gr8,gr4,gr8,icc0
84− cstd.p gr8,@(gr10,gr0) ,cc3,#1
85− corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */
86− beq icc3,#0,0b
87− bralr
88−
89− .size atomic64_add_return, .-atomic64_add_return
90−
91−###############################################################################
92−#
93−# long long atomic64_sub_return(long long i, atomic64_t *v)
94−#
95−###############################################################################
96− .globl atomic64_sub_return
97− .type atomic64_sub_return,@function
98−atomic64_sub_return:
99− or.p gr8,gr8,gr4
100− or gr9,gr9,gr5
101−0:
102− orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */
103− ckeq icc3,cc7
104− ldd.p @(gr10,gr0),gr8 /* LDD.P/ORCR must be atomic */
105− orcr cc7,cc7,cc3 /* set CC3 to true */
106− subcc gr9,gr5,gr9,icc0
107− subx gr8,gr4,gr8,icc0
108− cstd.p gr8,@(gr10,gr0) ,cc3,#1
109− corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */
110− beq icc3,#0,0b
111− bralr
112−
113− .size atomic64_sub_return, .-atomic64_sub_return
114−
11521 ###############################################################################
11622 #
11723 # uint64_t __xchg_64(uint64_t i, uint64_t *v)
arch/h8300/include/asm/atomic.h+35−102
@@ -16,83 +16,52 @@ · 15 unmodified lines
1616
1717 #include <linux/kernel.h>
1818
19−static inline int atomic_add_return(int i, atomic_t *v)
20−{
21− h8300flags flags;
22− int ret;
23−
24− flags = arch_local_irq_save();
25− ret = v->counter += i;
26− arch_local_irq_restore(flags);
27− return ret;
19+#define ATOMIC_OP_RETURN(op, c_op) \
20+static inline int atomic_##op##_return(int i, atomic_t *v) \
21+{ \
22+ h8300flags flags; \
23+ int ret; \
24+ \
25+ flags = arch_local_irq_save(); \
26+ ret = v->counter c_op i; \
27+ arch_local_irq_restore(flags); \
28+ return ret; \
2829 }
2930
30−#define atomic_add(i, v) atomic_add_return(i, v)
31−#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
32−
33−static inline int atomic_sub_return(int i, atomic_t *v)
34−{
35− h8300flags flags;
36− int ret;
37−
38− flags = arch_local_irq_save();
39− ret = v->counter -= i;
40− arch_local_irq_restore(flags);
41− return ret;
31+#define ATOMIC_OP(op, c_op) \
32+static inline void atomic_##op(int i, atomic_t *v) \
33+{ \
34+ h8300flags flags; \
35+ \
36+ flags = arch_local_irq_save(); \
37+ v->counter c_op i; \
38+ arch_local_irq_restore(flags); \
4239 }
4340
44−#define atomic_sub(i, v) atomic_sub_return(i, v)
45−#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0)
41+ATOMIC_OP_RETURN(add, +=)
42+ATOMIC_OP_RETURN(sub, -=)
4643
47−static inline int atomic_inc_return(atomic_t *v)
48−{
49− h8300flags flags;
50− int ret;
44+ATOMIC_OP(and, &=)
45+ATOMIC_OP(or, |=)
46+ATOMIC_OP(xor, ^=)
5147
52− flags = arch_local_irq_save();
53− v->counter++;
54− ret = v->counter;
55− arch_local_irq_restore(flags);
56− return ret;
57−}
58−
59−#define atomic_inc(v) atomic_inc_return(v)
48+#undef ATOMIC_OP_RETURN
49+#undef ATOMIC_OP
6050
61−/*
62− * atomic_inc_and_test - increment and test
63− * @v: pointer of type atomic_t
64− *
65− * Atomically increments @v by 1
66− * and returns true if the result is zero, or false for all
67− * other cases.
68− */
69−#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
51+#define atomic_add(i, v) (void)atomic_add_return(i, v)
52+#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
7053
71−static inline int atomic_dec_return(atomic_t *v)
72−{
73− h8300flags flags;
74− int ret;
54+#define atomic_sub(i, v) (void)atomic_sub_return(i, v)
55+#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0)
7556
76− flags = arch_local_irq_save();
77− --v->counter;
78− ret = v->counter;
79− arch_local_irq_restore(flags);
80− return ret;
81−}
57+#define atomic_inc_return(v) atomic_add_return(1, v)
58+#define atomic_dec_return(v) atomic_sub_return(1, v)
8259
83−#define atomic_dec(v) atomic_dec_return(v)
60+#define atomic_inc(v) (void)atomic_inc_return(v)
61+#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
8462
85−static inline int atomic_dec_and_test(atomic_t *v)
86−{
87− h8300flags flags;
88− int ret;
89−
90− flags = arch_local_irq_save();
91− --v->counter;
92− ret = v->counter;
93− arch_local_irq_restore(flags);
94− return ret == 0;
95−}
63+#define atomic_dec(v) (void)atomic_dec_return(v)
64+#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)
9665
9766 static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
9867 {
@@ -120,40 +89,4 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u) · 21 unmodified lines
12089 return ret;
12190 }
12291
123−static inline void atomic_clear_mask(unsigned long mask, unsigned long *v)
124−{
125− unsigned char ccr;
126− unsigned long tmp;
127−
128− __asm__ __volatile__("stc ccr,%w3\n\t"
129− "orc #0x80,ccr\n\t"
130− "mov.l %0,%1\n\t"
131− "and.l %2,%1\n\t"
132− "mov.l %1,%0\n\t"
133− "ldc %w3,ccr"
134− : "=m"(*v), "=r"(tmp)
135− : "g"(~(mask)), "r"(ccr));
136−}
137−
138−static inline void atomic_set_mask(unsigned long mask, unsigned long *v)
139−{
140− unsigned char ccr;
141− unsigned long tmp;
142−
143− __asm__ __volatile__("stc ccr,%w3\n\t"
144− "orc #0x80,ccr\n\t"
145− "mov.l %0,%1\n\t"
146− "or.l %2,%1\n\t"
147− "mov.l %1,%0\n\t"
148− "ldc %w3,ccr"
149− : "=m"(*v), "=r"(tmp)
150− : "g"(~(mask)), "r"(ccr));
151−}
152−
153−/* Atomic operations are already serializing */
154−#define smp_mb__before_atomic_dec() barrier()
155−#define smp_mb__after_atomic_dec() barrier()
156−#define smp_mb__before_atomic_inc() barrier()
157−#define smp_mb__after_atomic_inc() barrier()
158−
15992 #endif /* __ARCH_H8300_ATOMIC __ */
arch/hexagon/include/asm/atomic.h+4−0
@@ -132,6 +132,10 @@ static inline int atomic_##op##_return(int i, atomic_t *v) \ · 131 unmodified lines
132132 ATOMIC_OPS(add)
133133 ATOMIC_OPS(sub)
134134
135+ATOMIC_OP(and)
136+ATOMIC_OP(or)
137+ATOMIC_OP(xor)
138+
135139 #undef ATOMIC_OPS
136140 #undef ATOMIC_OP_RETURN
137141 #undef ATOMIC_OP
arch/ia64/include/asm/atomic.h+20−4
@@ -45,8 +45,6 @@ ia64_atomic_##op (int i, atomic_t *v) \ · 44 unmodified lines
4545 ATOMIC_OP(add, +)
4646 ATOMIC_OP(sub, -)
4747
48−#undef ATOMIC_OP
49−
5048 #define atomic_add_return(i,v) \
5149 ({ \
5250 int __ia64_aar_i = (i); \
@@ -71,6 +69,16 @@ ATOMIC_OP(sub, -) · 18 unmodified lines
7169 : ia64_atomic_sub(__ia64_asr_i, v); \
7270 })
7371
72+ATOMIC_OP(and, &)
73+ATOMIC_OP(or, |)
74+ATOMIC_OP(xor, ^)
75+
76+#define atomic_and(i,v) (void)ia64_atomic_and(i,v)
77+#define atomic_or(i,v) (void)ia64_atomic_or(i,v)
78+#define atomic_xor(i,v) (void)ia64_atomic_xor(i,v)
79+
80+#undef ATOMIC_OP
81+
7482 #define ATOMIC64_OP(op, c_op) \
7583 static __inline__ long \
7684 ia64_atomic64_##op (__s64 i, atomic64_t *v) \
@@ -89,8 +97,6 @@ ia64_atomic64_##op (__s64 i, atomic64_t *v) \ · 12 unmodified lines
8997 ATOMIC64_OP(add, +)
9098 ATOMIC64_OP(sub, -)
9199
92−#undef ATOMIC64_OP
93−
94100 #define atomic64_add_return(i,v) \
95101 ({ \
96102 long __ia64_aar_i = (i); \
@@ -115,6 +121,16 @@ ATOMIC64_OP(sub, -) · 18 unmodified lines
115121 : ia64_atomic64_sub(__ia64_asr_i, v); \
116122 })
117123
124+ATOMIC64_OP(and, &)
125+ATOMIC64_OP(or, |)
126+ATOMIC64_OP(xor, ^)
127+
128+#define atomic64_and(i,v) (void)ia64_atomic64_and(i,v)
129+#define atomic64_or(i,v) (void)ia64_atomic64_or(i,v)
130+#define atomic64_xor(i,v) (void)ia64_atomic64_xor(i,v)
131+
132+#undef ATOMIC64_OP
133+
118134 #define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
119135 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
120136
arch/ia64/include/asm/barrier.h+2−2
@@ -66,12 +66,12 @@ · 65 unmodified lines
6666 do { \
6767 compiletime_assert_atomic_type(*p); \
6868 barrier(); \
69− ACCESS_ONCE(*p) = (v); \
69+ WRITE_ONCE(*p, v); \
7070 } while (0)
7171
7272 #define smp_load_acquire(p) \
7373 ({ \
74− typeof(*p) ___p1 = ACCESS_ONCE(*p); \
74+ typeof(*p) ___p1 = READ_ONCE(*p); \
7575 compiletime_assert_atomic_type(*p); \
7676 barrier(); \
7777 ___p1; \
arch/m32r/include/asm/atomic.h+4−41
@@ -94,6 +94,10 @@ static __inline__ int atomic_##op##_return(int i, atomic_t *v) \ · 93 unmodified lines
9494 ATOMIC_OPS(add)
9595 ATOMIC_OPS(sub)
9696
97+ATOMIC_OP(and)
98+ATOMIC_OP(or)
99+ATOMIC_OP(xor)
100+
97101 #undef ATOMIC_OPS
98102 #undef ATOMIC_OP_RETURN
99103 #undef ATOMIC_OP
@@ -239,45 +243,4 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) · 139 unmodified lines
239243 return c;
240244 }
241245
242−
243−static __inline__ void atomic_clear_mask(unsigned long mask, atomic_t *addr)
244−{
245− unsigned long flags;
246− unsigned long tmp;
247−
248− local_irq_save(flags);
249− __asm__ __volatile__ (
250− "# atomic_clear_mask \n\t"
251− DCACHE_CLEAR("%0", "r5", "%1")
252− M32R_LOCK" %0, @%1; \n\t"
253− "and %0, %2; \n\t"
254− M32R_UNLOCK" %0, @%1; \n\t"
255− : "=&r" (tmp)
256− : "r" (addr), "r" (~mask)
257− : "memory"
258− __ATOMIC_CLOBBER
259− );
260− local_irq_restore(flags);
261−}
262−
263−static __inline__ void atomic_set_mask(unsigned long mask, atomic_t *addr)
264−{
265− unsigned long flags;
266− unsigned long tmp;
267−
268− local_irq_save(flags);
269− __asm__ __volatile__ (
270− "# atomic_set_mask \n\t"
271− DCACHE_CLEAR("%0", "r5", "%1")
272− M32R_LOCK" %0, @%1; \n\t"
273− "or %0, %2; \n\t"
274− M32R_UNLOCK" %0, @%1; \n\t"
275− : "=&r" (tmp)
276− : "r" (addr), "r" (mask)
277− : "memory"
278− __ATOMIC_CLOBBER
279− );
280− local_irq_restore(flags);
281−}
282−
283246 #endif /* _ASM_M32R_ATOMIC_H */
arch/m32r/kernel/smp.c+2−2
@@ -156,7 +156,7 @@ void smp_flush_cache_all(void) · 155 unmodified lines
156156 cpumask_clear_cpu(smp_processor_id(), &cpumask);
157157 spin_lock(&flushcache_lock);
158158 mask=cpumask_bits(&cpumask);
159− atomic_set_mask(*mask, (atomic_t *)&flushcache_cpumask);
159+ atomic_or(*mask, (atomic_t *)&flushcache_cpumask);
160160 send_IPI_mask(&cpumask, INVALIDATE_CACHE_IPI, 0);
161161 _flush_cache_copyback_all();
162162 while (flushcache_cpumask)
@@ -407,7 +407,7 @@ static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm, · 244 unmodified lines
407407 flush_vma = vma;
408408 flush_va = va;
409409 mask=cpumask_bits(&cpumask);
410− atomic_set_mask(*mask, (atomic_t *)&flush_cpumask);
410+ atomic_or(*mask, (atomic_t *)&flush_cpumask);
411411
412412 /*
413413 * We have to send the IPI only to
arch/m68k/include/asm/atomic.h+4−10
@@ -77,6 +77,10 @@ static inline int atomic_##op##_return(int i, atomic_t * v) \ · 76 unmodified lines
7777 ATOMIC_OPS(add, +=, add)
7878 ATOMIC_OPS(sub, -=, sub)
7979
80+ATOMIC_OP(and, &=, and)
81+ATOMIC_OP(or, |=, or)
82+ATOMIC_OP(xor, ^=, eor)
83+
8084 #undef ATOMIC_OPS
8185 #undef ATOMIC_OP_RETURN
8286 #undef ATOMIC_OP
@@ -170,16 +174,6 @@ static inline int atomic_add_negative(int i, atomic_t *v) · 87 unmodified lines
170174 return c != 0;
171175 }
172176
173−static inline void atomic_clear_mask(unsigned long mask, unsigned long *v)
174−{
175− __asm__ __volatile__("andl %1,%0" : "+m" (*v) : ASM_DI (~(mask)));
176−}
177−
178−static inline void atomic_set_mask(unsigned long mask, unsigned long *v)
179−{
180− __asm__ __volatile__("orl %1,%0" : "+m" (*v) : ASM_DI (mask));
181−}
182−
183177 static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
184178 {
185179 int c, old;
arch/metag/include/asm/atomic_lnkget.h+4−34
@@ -74,44 +74,14 @@ static inline int atomic_##op##_return(int i, atomic_t *v) \ · 73 unmodified lines
7474 ATOMIC_OPS(add)
7575 ATOMIC_OPS(sub)
7676
77+ATOMIC_OP(and)
78+ATOMIC_OP(or)
79+ATOMIC_OP(xor)
80+
7781 #undef ATOMIC_OPS
7882 #undef ATOMIC_OP_RETURN
7983 #undef ATOMIC_OP
8084
81−static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
82−{
83− int temp;
84−
85− asm volatile (
86− "1: LNKGETD %0, [%1]\n"
87− " AND %0, %0, %2\n"
88− " LNKSETD [%1] %0\n"
89− " DEFR %0, TXSTAT\n"
90− " ANDT %0, %0, #HI(0x3f000000)\n"
91− " CMPT %0, #HI(0x02000000)\n"
92− " BNZ 1b\n"
93− : "=&d" (temp)
94− : "da" (&v->counter), "bd" (~mask)
95− : "cc");
96−}
97−
98−static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
99−{
100− int temp;
101−
102− asm volatile (
103− "1: LNKGETD %0, [%1]\n"
104− " OR %0, %0, %2\n"
105− " LNKSETD [%1], %0\n"
106− " DEFR %0, TXSTAT\n"
107− " ANDT %0, %0, #HI(0x3f000000)\n"
108− " CMPT %0, #HI(0x02000000)\n"
109− " BNZ 1b\n"
110− : "=&d" (temp)
111− : "da" (&v->counter), "bd" (mask)
112− : "cc");
113−}
114−
11585 static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
11686 {
11787 int result, temp;
arch/metag/include/asm/atomic_lock1.h+3−20
@@ -68,31 +68,14 @@ static inline int atomic_##op##_return(int i, atomic_t *v) \ · 67 unmodified lines
6868
6969 ATOMIC_OPS(add, +=)
7070 ATOMIC_OPS(sub, -=)
71+ATOMIC_OP(and, &=)
72+ATOMIC_OP(or, |=)
73+ATOMIC_OP(xor, ^=)
7174
7275 #undef ATOMIC_OPS
7376 #undef ATOMIC_OP_RETURN
7477 #undef ATOMIC_OP
7578
76−static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
77−{
78− unsigned long flags;
79−
80− __global_lock1(flags);
81− fence();
82− v->counter &= ~mask;
83− __global_unlock1(flags);
84−}
85−
86−static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
87−{
88− unsigned long flags;
89−
90− __global_lock1(flags);
91− fence();
92− v->counter |= mask;
93− __global_unlock1(flags);
94−}
95−
9679 static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
9780 {
9881 int ret;
arch/metag/include/asm/barrier.h+2−2
@@ -90,12 +90,12 @@ static inline void fence(void) · 89 unmodified lines
9090 do { \
9191 compiletime_assert_atomic_type(*p); \
9292 smp_mb(); \
93− ACCESS_ONCE(*p) = (v); \
93+ WRITE_ONCE(*p, v); \
9494 } while (0)
9595
9696 #define smp_load_acquire(p) \
9797 ({ \
98− typeof(*p) ___p1 = ACCESS_ONCE(*p); \
98+ typeof(*p) ___p1 = READ_ONCE(*p); \
9999 compiletime_assert_atomic_type(*p); \
100100 smp_mb(); \
101101 ___p1; \
arch/mips/include/asm/atomic.h+7−0
@@ -137,6 +137,10 @@ static __inline__ int atomic_##op##_return(int i, atomic_t * v) \ · 136 unmodified lines
137137 ATOMIC_OPS(add, +=, addu)
138138 ATOMIC_OPS(sub, -=, subu)
139139
140+ATOMIC_OP(and, &=, and)
141+ATOMIC_OP(or, |=, or)
142+ATOMIC_OP(xor, ^=, xor)
143+
140144 #undef ATOMIC_OPS
141145 #undef ATOMIC_OP_RETURN
142146 #undef ATOMIC_OP
@@ -416,6 +420,9 @@ static __inline__ long atomic64_##op##_return(long i, atomic64_t * v) \ · 273 unmodified lines
416420
417421 ATOMIC64_OPS(add, +=, daddu)
418422 ATOMIC64_OPS(sub, -=, dsubu)
423+ATOMIC64_OP(and, &=, and)
424+ATOMIC64_OP(or, |=, or)
425+ATOMIC64_OP(xor, ^=, xor)
419426
420427 #undef ATOMIC64_OPS
421428 #undef ATOMIC64_OP_RETURN
arch/mips/include/asm/barrier.h+2−2
@@ -133,12 +133,12 @@ · 132 unmodified lines
133133 do { \
134134 compiletime_assert_atomic_type(*p); \
135135 smp_mb(); \
136− ACCESS_ONCE(*p) = (v); \
136+ WRITE_ONCE(*p, v); \
137137 } while (0)
138138
139139 #define smp_load_acquire(p) \
140140 ({ \
141− typeof(*p) ___p1 = ACCESS_ONCE(*p); \
141+ typeof(*p) ___p1 = READ_ONCE(*p); \
142142 compiletime_assert_atomic_type(*p); \
143143 smp_mb(); \
144144 ___p1; \
arch/mips/include/asm/jump_label.h+17−2
@@ -26,14 +26,29 @@ · 25 unmodified lines
2626 #define NOP_INSN "nop"
2727 #endif
2828
29−static __always_inline bool arch_static_branch(struct static_key *key)
29+static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
3030 {
3131 asm_volatile_goto("1:\t" NOP_INSN "\n\t"
3232 "nop\n\t"
3333 ".pushsection __jump_table, \"aw\"\n\t"
3434 WORD_INSN " 1b, %l[l_yes], %0\n\t"
3535 ".popsection\n\t"
36− : : "i" (key) : : l_yes);
36+ : : "i" (&((char *)key)[branch]) : : l_yes);
37+
38+ return false;
39+l_yes:
40+ return true;
41+}
42+
43+static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
44+{
45+ asm_volatile_goto("1:\tj %l[l_yes]\n\t"
46+ "nop\n\t"
47+ ".pushsection __jump_table, \"aw\"\n\t"
48+ WORD_INSN " 1b, %l[l_yes], %0\n\t"
49+ ".popsection\n\t"
50+ : : "i" (&((char *)key)[branch]) : : l_yes);
51+
3752 return false;
3853 l_yes:
3954 return true;
arch/mips/kernel/jump_label.c+1−1
@@ -51,7 +51,7 @@ void arch_jump_label_transform(struct jump_entry *e, · 50 unmodified lines
5151 /* Target must have the right alignment and ISA must be preserved. */
5252 BUG_ON((e->target & J_ALIGN_MASK) != J_ISA_BIT);
5353
54− if (type == JUMP_LABEL_ENABLE) {
54+ if (type == JUMP_LABEL_JMP) {
5555 insn.j_format.opcode = J_ISA_BIT ? mm_j32_op : j_op;
5656 insn.j_format.target = e->target >> J_RANGE_SHIFT;
5757 } else {
arch/mn10300/include/asm/atomic.h+4−67
@@ -89,6 +89,10 @@ static inline int atomic_##op##_return(int i, atomic_t *v) \ · 88 unmodified lines
8989 ATOMIC_OPS(add)
9090 ATOMIC_OPS(sub)
9191
92+ATOMIC_OP(and)
93+ATOMIC_OP(or)
94+ATOMIC_OP(xor)
95+
9296 #undef ATOMIC_OPS
9397 #undef ATOMIC_OP_RETURN
9498 #undef ATOMIC_OP
@@ -127,73 +131,6 @@ static inline void atomic_dec(atomic_t *v) · 32 unmodified lines
127131 #define atomic_xchg(ptr, v) (xchg(&(ptr)->counter, (v)))
128132 #define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
129133
130−/**
131− * atomic_clear_mask - Atomically clear bits in memory
132− * @mask: Mask of the bits to be cleared
133− * @v: pointer to word in memory
134− *
135− * Atomically clears the bits set in mask from the memory word specified.
136− */
137−static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
138−{
139−#ifdef CONFIG_SMP
140− int status;
141−
142− asm volatile(
143− "1: mov %3,(_AAR,%2) \n"
144− " mov (_ADR,%2),%0 \n"
145− " and %4,%0 \n"
146− " mov %0,(_ADR,%2) \n"
147− " mov (_ADR,%2),%0 \n" /* flush */
148− " mov (_ASR,%2),%0 \n"
149− " or %0,%0 \n"
150− " bne 1b \n"
151− : "=&r"(status), "=m"(*addr)
152− : "a"(ATOMIC_OPS_BASE_ADDR), "r"(addr), "r"(~mask)
153− : "memory", "cc");
154−#else
155− unsigned long flags;
156−
157− mask = ~mask;
158− flags = arch_local_cli_save();
159− *addr &= mask;
160− arch_local_irq_restore(flags);
161−#endif
162−}
163−
164−/**
165− * atomic_set_mask - Atomically set bits in memory
166− * @mask: Mask of the bits to be set
167− * @v: pointer to word in memory
168− *
169− * Atomically sets the bits set in mask from the memory word specified.
170− */
171−static inline void atomic_set_mask(unsigned long mask, unsigned long *addr)
172−{
173−#ifdef CONFIG_SMP
174− int status;
175−
176− asm volatile(
177− "1: mov %3,(_AAR,%2) \n"
178− " mov (_ADR,%2),%0 \n"
179− " or %4,%0 \n"
180− " mov %0,(_ADR,%2) \n"
181− " mov (_ADR,%2),%0 \n" /* flush */
182− " mov (_ASR,%2),%0 \n"
183− " or %0,%0 \n"
184− " bne 1b \n"
185− : "=&r"(status), "=m"(*addr)
186− : "a"(ATOMIC_OPS_BASE_ADDR), "r"(addr), "r"(mask)
187− : "memory", "cc");
188−#else
189− unsigned long flags;
190−
191− flags = arch_local_cli_save();
192− *addr |= mask;
193− arch_local_irq_restore(flags);
194−#endif
195−}
196−
197134 #endif /* __KERNEL__ */
198135 #endif /* CONFIG_SMP */
199136 #endif /* _ASM_ATOMIC_H */
arch/mn10300/mm/tlb-smp.c+1−1
@@ -119,7 +119,7 @@ static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm, · 118 unmodified lines
119119 flush_mm = mm;
120120 flush_va = va;
121121 #if NR_CPUS <= BITS_PER_LONG
122− atomic_set_mask(cpumask.bits[0], &flush_cpumask.bits[0]);
122+ atomic_or(cpumask.bits[0], (atomic_t *)&flush_cpumask.bits[0]);
123123 #else
124124 #error Not supported.
125125 #endif
arch/parisc/configs/c8000_defconfig+0−1
@@ -242,7 +242,6 @@ CONFIG_LOCKUP_DETECTOR=y · 241 unmodified lines
242242 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
243243 CONFIG_PANIC_ON_OOPS=y
244244 CONFIG_DEBUG_RT_MUTEXES=y
245−CONFIG_RT_MUTEX_TESTER=y
246245 CONFIG_PROVE_RCU_DELAY=y
247246 CONFIG_DEBUG_BLOCK_EXT_DEVT=y
248247 CONFIG_LATENCYTOP=y
arch/parisc/configs/generic-32bit_defconfig+0−1
@@ -295,7 +295,6 @@ CONFIG_DEBUG_SHIRQ=y · 294 unmodified lines
295295 CONFIG_DETECT_HUNG_TASK=y
296296 CONFIG_TIMER_STATS=y
297297 CONFIG_DEBUG_RT_MUTEXES=y
298−CONFIG_RT_MUTEX_TESTER=y
299298 CONFIG_DEBUG_SPINLOCK=y
300299 CONFIG_DEBUG_MUTEXES=y
301300 CONFIG_RCU_CPU_STALL_INFO=y
arch/parisc/include/asm/atomic.h+7−0
@@ -126,6 +126,10 @@ static __inline__ int atomic_##op##_return(int i, atomic_t *v) \ · 125 unmodified lines
126126 ATOMIC_OPS(add, +=)
127127 ATOMIC_OPS(sub, -=)
128128
129+ATOMIC_OP(and, &=)
130+ATOMIC_OP(or, |=)
131+ATOMIC_OP(xor, ^=)
132+
129133 #undef ATOMIC_OPS
130134 #undef ATOMIC_OP_RETURN
131135 #undef ATOMIC_OP
@@ -185,6 +189,9 @@ static __inline__ s64 atomic64_##op##_return(s64 i, atomic64_t *v) \ · 53 unmodified lines
185189
186190 ATOMIC64_OPS(add, +=)
187191 ATOMIC64_OPS(sub, -=)
192+ATOMIC64_OP(and, &=)
193+ATOMIC64_OP(or, |=)
194+ATOMIC64_OP(xor, ^=)
188195
189196 #undef ATOMIC64_OPS
190197 #undef ATOMIC64_OP_RETURN
arch/powerpc/include/asm/atomic.h+7−0
@@ -67,6 +67,10 @@ static __inline__ int atomic_##op##_return(int a, atomic_t *v) \ · 66 unmodified lines
6767 ATOMIC_OPS(add, add)
6868 ATOMIC_OPS(sub, subf)
6969
70+ATOMIC_OP(and, and)
71+ATOMIC_OP(or, or)
72+ATOMIC_OP(xor, xor)
73+
7074 #undef ATOMIC_OPS
7175 #undef ATOMIC_OP_RETURN
7276 #undef ATOMIC_OP
@@ -304,6 +308,9 @@ static __inline__ long atomic64_##op##_return(long a, atomic64_t *v) \ · 231 unmodified lines
304308
305309 ATOMIC64_OPS(add, add)
306310 ATOMIC64_OPS(sub, subf)
311+ATOMIC64_OP(and, and)
312+ATOMIC64_OP(or, or)
313+ATOMIC64_OP(xor, xor)
307314
308315 #undef ATOMIC64_OPS
309316 #undef ATOMIC64_OP_RETURN
arch/powerpc/include/asm/barrier.h+2−2
@@ -76,12 +76,12 @@ · 75 unmodified lines
7676 do { \
7777 compiletime_assert_atomic_type(*p); \
7878 smp_lwsync(); \
79− ACCESS_ONCE(*p) = (v); \
79+ WRITE_ONCE(*p, v); \
8080 } while (0)
8181
8282 #define smp_load_acquire(p) \
8383 ({ \
84− typeof(*p) ___p1 = ACCESS_ONCE(*p); \
84+ typeof(*p) ___p1 = READ_ONCE(*p); \
8585 compiletime_assert_atomic_type(*p); \
8686 smp_lwsync(); \
8787 ___p1; \
arch/powerpc/include/asm/jump_label.h+17−2
@@ -18,14 +18,29 @@ · 17 unmodified lines
1818 #define JUMP_ENTRY_TYPE stringify_in_c(FTR_ENTRY_LONG)
1919 #define JUMP_LABEL_NOP_SIZE 4
2020
21−static __always_inline bool arch_static_branch(struct static_key *key)
21+static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
2222 {
2323 asm_volatile_goto("1:\n\t"
2424 "nop\n\t"
2525 ".pushsection __jump_table, \"aw\"\n\t"
2626 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
2727 ".popsection \n\t"
28− : : "i" (key) : : l_yes);
28+ : : "i" (&((char *)key)[branch]) : : l_yes);
29+
30+ return false;
31+l_yes:
32+ return true;
33+}
34+
35+static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
36+{
37+ asm_volatile_goto("1:\n\t"
38+ "b %l[l_yes]\n\t"
39+ ".pushsection __jump_table, \"aw\"\n\t"
40+ JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
41+ ".popsection \n\t"
42+ : : "i" (&((char *)key)[branch]) : : l_yes);
43+
2944 return false;
3045 l_yes:
3146 return true;
arch/powerpc/kernel/jump_label.c+1−1
@@ -17,7 +17,7 @@ void arch_jump_label_transform(struct jump_entry *entry, · 16 unmodified lines
1717 {
1818 u32 *addr = (u32 *)(unsigned long)entry->code;
1919
20− if (type == JUMP_LABEL_ENABLE)
20+ if (type == JUMP_LABEL_JMP)
2121 patch_branch(addr, entry->target, 0);
2222 else
2323 patch_instruction(addr, PPC_INST_NOP);
arch/powerpc/kernel/misc_32.S+0−19
@@ -595,25 +595,6 @@ _GLOBAL(copy_page) · 594 unmodified lines
595595 li r11,4
596596 b 2b
597597
598−/*
599− * void atomic_clear_mask(atomic_t mask, atomic_t *addr)
600− * void atomic_set_mask(atomic_t mask, atomic_t *addr);
601− */
602−_GLOBAL(atomic_clear_mask)
603−10: lwarx r5,0,r4
604− andc r5,r5,r3
605− PPC405_ERR77(0,r4)
606− stwcx. r5,0,r4
607− bne- 10b
608− blr
609−_GLOBAL(atomic_set_mask)
610−10: lwarx r5,0,r4
611− or r5,r5,r3
612− PPC405_ERR77(0,r4)
613− stwcx. r5,0,r4
614− bne- 10b
615− blr
616−
617598 /*
618599 * Extended precision shifts.
619600 *
arch/s390/include/asm/atomic.h+24−17
@@ -27,6 +27,7 @@ · 26 unmodified lines
2727 #define __ATOMIC_OR "lao"
2828 #define __ATOMIC_AND "lan"
2929 #define __ATOMIC_ADD "laa"
30+#define __ATOMIC_XOR "lax"
3031 #define __ATOMIC_BARRIER "bcr 14,0\n"
3132
3233 #define __ATOMIC_LOOP(ptr, op_val, op_string, __barrier) \
@@ -49,6 +50,7 @@ · 16 unmodified lines
4950 #define __ATOMIC_OR "or"
5051 #define __ATOMIC_AND "nr"
5152 #define __ATOMIC_ADD "ar"
53+#define __ATOMIC_XOR "xr"
5254 #define __ATOMIC_BARRIER "\n"
5355
5456 #define __ATOMIC_LOOP(ptr, op_val, op_string, __barrier) \
@@ -118,15 +120,17 @@ static inline void atomic_add(int i, atomic_t *v) · 63 unmodified lines
118120 #define atomic_dec_return(_v) atomic_sub_return(1, _v)
119121 #define atomic_dec_and_test(_v) (atomic_sub_return(1, _v) == 0)
120122
121−static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
122−{
123− __ATOMIC_LOOP(v, ~mask, __ATOMIC_AND, __ATOMIC_NO_BARRIER);
123+#define ATOMIC_OP(op, OP) \
124+static inline void atomic_##op(int i, atomic_t *v) \
125+{ \
126+ __ATOMIC_LOOP(v, i, __ATOMIC_##OP, __ATOMIC_NO_BARRIER); \
124127 }
125128
126−static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
127−{
128− __ATOMIC_LOOP(v, mask, __ATOMIC_OR, __ATOMIC_NO_BARRIER);
129−}
129+ATOMIC_OP(and, AND)
130+ATOMIC_OP(or, OR)
131+ATOMIC_OP(xor, XOR)
132+
133+#undef ATOMIC_OP
130134
131135 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
132136
@@ -167,6 +171,7 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u) · 34 unmodified lines
167171 #define __ATOMIC64_OR "laog"
168172 #define __ATOMIC64_AND "lang"
169173 #define __ATOMIC64_ADD "laag"
174+#define __ATOMIC64_XOR "laxg"
170175 #define __ATOMIC64_BARRIER "bcr 14,0\n"
171176
172177 #define __ATOMIC64_LOOP(ptr, op_val, op_string, __barrier) \
@@ -189,6 +194,7 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u) · 16 unmodified lines
189194 #define __ATOMIC64_OR "ogr"
190195 #define __ATOMIC64_AND "ngr"
191196 #define __ATOMIC64_ADD "agr"
197+#define __ATOMIC64_XOR "xgr"
192198 #define __ATOMIC64_BARRIER "\n"
193199
194200 #define __ATOMIC64_LOOP(ptr, op_val, op_string, __barrier) \
@@ -247,16 +253,6 @@ static inline void atomic64_add(long long i, atomic64_t *v) · 52 unmodified lines
247253 __ATOMIC64_LOOP(v, i, __ATOMIC64_ADD, __ATOMIC64_NO_BARRIER);
248254 }
249255
250−static inline void atomic64_clear_mask(unsigned long mask, atomic64_t *v)
251−{
252− __ATOMIC64_LOOP(v, ~mask, __ATOMIC64_AND, __ATOMIC64_NO_BARRIER);
253−}
254−
255−static inline void atomic64_set_mask(unsigned long mask, atomic64_t *v)
256−{
257− __ATOMIC64_LOOP(v, mask, __ATOMIC64_OR, __ATOMIC64_NO_BARRIER);
258−}
259−
260256 #define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
261257
262258 static inline long long atomic64_cmpxchg(atomic64_t *v,
@@ -270,6 +266,17 @@ static inline long long atomic64_cmpxchg(atomic64_t *v, · 7 unmodified lines
270266 return old;
271267 }
272268
269+#define ATOMIC64_OP(op, OP) \
270+static inline void atomic64_##op(long i, atomic64_t *v) \
271+{ \
272+ __ATOMIC64_LOOP(v, i, __ATOMIC64_##OP, __ATOMIC64_NO_BARRIER); \
273+}
274+
275+ATOMIC64_OP(and, AND)
276+ATOMIC64_OP(or, OR)
277+ATOMIC64_OP(xor, XOR)
278+
279+#undef ATOMIC64_OP
273280 #undef __ATOMIC64_LOOP
274281
275282 static inline int atomic64_add_unless(atomic64_t *v, long long i, long long u)
arch/s390/include/asm/barrier.h+2−2
@@ -42,12 +42,12 @@ · 41 unmodified lines
4242 do { \
4343 compiletime_assert_atomic_type(*p); \
4444 barrier(); \
45− ACCESS_ONCE(*p) = (v); \
45+ WRITE_ONCE(*p, v); \
4646 } while (0)
4747
4848 #define smp_load_acquire(p) \
4949 ({ \
50− typeof(*p) ___p1 = ACCESS_ONCE(*p); \
50+ typeof(*p) ___p1 = READ_ONCE(*p); \
5151 compiletime_assert_atomic_type(*p); \
5252 barrier(); \
5353 ___p1; \
arch/s390/include/asm/jump_label.h+17−2
@@ -12,14 +12,29 @@ · 11 unmodified lines
1212 * We use a brcl 0,2 instruction for jump labels at compile time so it
1313 * can be easily distinguished from a hotpatch generated instruction.
1414 */
15−static __always_inline bool arch_static_branch(struct static_key *key)
15+static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
1616 {
1717 asm_volatile_goto("0: brcl 0,"__stringify(JUMP_LABEL_NOP_OFFSET)"\n"
1818 ".pushsection __jump_table, \"aw\"\n"
1919 ".balign 8\n"
2020 ".quad 0b, %l[label], %0\n"
2121 ".popsection\n"
22− : : "X" (key) : : label);
22+ : : "X" (&((char *)key)[branch]) : : label);
23+
24+ return false;
25+label:
26+ return true;
27+}
28+
29+static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
30+{
31+ asm_volatile_goto("0: brcl 15, %l[label]\n"
32+ ".pushsection __jump_table, \"aw\"\n"
33+ ".balign 8\n"
34+ ".quad 0b, %l[label], %0\n"
35+ ".popsection\n"
36+ : : "X" (&((char *)key)[branch]) : : label);
37+
2338 return false;
2439 label:
2540 return true;
arch/s390/kernel/jump_label.c+1−1
@@ -61,7 +61,7 @@ static void __jump_label_transform(struct jump_entry *entry, · 60 unmodified lines
6161 {
6262 struct insn old, new;
6363
64− if (type == JUMP_LABEL_ENABLE) {
64+ if (type == JUMP_LABEL_JMP) {
6565 jump_label_make_nop(entry, &old);
6666 jump_label_make_branch(entry, &new);
6767 } else {
arch/s390/kernel/time.c+2−2
@@ -378,7 +378,7 @@ static void disable_sync_clock(void *dummy) · 377 unmodified lines
378378 * increase the "sequence" counter to avoid the race of an
379379 * etr event and the complete recovery against get_sync_clock.
380380 */
381− atomic_clear_mask(0x80000000, sw_ptr);
381+ atomic_andnot(0x80000000, sw_ptr);
382382 atomic_inc(sw_ptr);
383383 }
384384
@@ -389,7 +389,7 @@ static void disable_sync_clock(void *dummy) · 4 unmodified lines
389389 static void enable_sync_clock(void)
390390 {
391391 atomic_t *sw_ptr = this_cpu_ptr(&clock_sync_word);
392− atomic_set_mask(0x80000000, sw_ptr);
392+ atomic_or(0x80000000, sw_ptr);
393393 }
394394
395395 /*
arch/s390/kvm/interrupt.c+15−15
@@ -173,20 +173,20 @@ static unsigned long deliverable_irqs(struct kvm_vcpu *vcpu) · 172 unmodified lines
173173
174174 static void __set_cpu_idle(struct kvm_vcpu *vcpu)
175175 {
176− atomic_set_mask(CPUSTAT_WAIT, &vcpu->arch.sie_block->cpuflags);
176+ atomic_or(CPUSTAT_WAIT, &vcpu->arch.sie_block->cpuflags);
177177 set_bit(vcpu->vcpu_id, vcpu->arch.local_int.float_int->idle_mask);
178178 }
179179
180180 static void __unset_cpu_idle(struct kvm_vcpu *vcpu)
181181 {
182− atomic_clear_mask(CPUSTAT_WAIT, &vcpu->arch.sie_block->cpuflags);
182+ atomic_andnot(CPUSTAT_WAIT, &vcpu->arch.sie_block->cpuflags);
183183 clear_bit(vcpu->vcpu_id, vcpu->arch.local_int.float_int->idle_mask);
184184 }
185185
186186 static void __reset_intercept_indicators(struct kvm_vcpu *vcpu)
187187 {
188− atomic_clear_mask(CPUSTAT_IO_INT | CPUSTAT_EXT_INT | CPUSTAT_STOP_INT,
189− &vcpu->arch.sie_block->cpuflags);
188+ atomic_andnot(CPUSTAT_IO_INT | CPUSTAT_EXT_INT | CPUSTAT_STOP_INT,
189+ &vcpu->arch.sie_block->cpuflags);
190190 vcpu->arch.sie_block->lctl = 0x0000;
191191 vcpu->arch.sie_block->ictl &= ~(ICTL_LPSW | ICTL_STCTL | ICTL_PINT);
192192
@@ -199,7 +199,7 @@ static void __reset_intercept_indicators(struct kvm_vcpu *vcpu) · 6 unmodified lines
199199
200200 static void __set_cpuflag(struct kvm_vcpu *vcpu, u32 flag)
201201 {
202− atomic_set_mask(flag, &vcpu->arch.sie_block->cpuflags);
202+ atomic_or(flag, &vcpu->arch.sie_block->cpuflags);
203203 }
204204
205205 static void set_intercept_indicators_io(struct kvm_vcpu *vcpu)
@@ -928,7 +928,7 @@ void kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu) · 722 unmodified lines
928928 spin_unlock(&li->lock);
929929
930930 /* clear pending external calls set by sigp interpretation facility */
931− atomic_clear_mask(CPUSTAT_ECALL_PEND, li->cpuflags);
931+ atomic_andnot(CPUSTAT_ECALL_PEND, li->cpuflags);
932932 vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sigp_ctrl = 0;
933933 }
934934
@@ -1026,7 +1026,7 @@ static int __inject_pfault_init(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq) · 91 unmodified lines
10261026
10271027 li->irq.ext = irq->u.ext;
10281028 set_bit(IRQ_PEND_PFAULT_INIT, &li->pending_irqs);
1029− atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
1029+ atomic_or(CPUSTAT_EXT_INT, li->cpuflags);
10301030 return 0;
10311031 }
10321032
@@ -1041,7 +1041,7 @@ static int __inject_extcall_sigpif(struct kvm_vcpu *vcpu, uint16_t src_id) · 8 unmodified lines
10411041 /* another external call is pending */
10421042 return -EBUSY;
10431043 }
1044− atomic_set_mask(CPUSTAT_ECALL_PEND, &vcpu->arch.sie_block->cpuflags);
1044+ atomic_or(CPUSTAT_ECALL_PEND, &vcpu->arch.sie_block->cpuflags);
10451045 return 0;
10461046 }
10471047
@@ -1067,7 +1067,7 @@ static int __inject_extcall(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq) · 19 unmodified lines
10671067 if (test_and_set_bit(IRQ_PEND_EXT_EXTERNAL, &li->pending_irqs))
10681068 return -EBUSY;
10691069 *extcall = irq->u.extcall;
1070− atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
1070+ atomic_or(CPUSTAT_EXT_INT, li->cpuflags);
10711071 return 0;
10721072 }
10731073
@@ -1139,7 +1139,7 @@ static int __inject_sigp_emergency(struct kvm_vcpu *vcpu, · 65 unmodified lines
11391139
11401140 set_bit(irq->u.emerg.code, li->sigp_emerg_pending);
11411141 set_bit(IRQ_PEND_EXT_EMERGENCY, &li->pending_irqs);
1142− atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
1142+ atomic_or(CPUSTAT_EXT_INT, li->cpuflags);
11431143 return 0;
11441144 }
11451145
@@ -1183,7 +1183,7 @@ static int __inject_ckc(struct kvm_vcpu *vcpu) · 37 unmodified lines
11831183 0, 0);
11841184
11851185 set_bit(IRQ_PEND_EXT_CLOCK_COMP, &li->pending_irqs);
1186− atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
1186+ atomic_or(CPUSTAT_EXT_INT, li->cpuflags);
11871187 return 0;
11881188 }
11891189
@@ -1196,7 +1196,7 @@ static int __inject_cpu_timer(struct kvm_vcpu *vcpu) · 6 unmodified lines
11961196 0, 0);
11971197
11981198 set_bit(IRQ_PEND_EXT_CPU_TIMER, &li->pending_irqs);
1199− atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
1199+ atomic_or(CPUSTAT_EXT_INT, li->cpuflags);
12001200 return 0;
12011201 }
12021202
@@ -1375,13 +1375,13 @@ static void __floating_irq_kick(struct kvm *kvm, u64 type) · 172 unmodified lines
13751375 spin_lock(&li->lock);
13761376 switch (type) {
13771377 case KVM_S390_MCHK:
1378− atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags);
1378+ atomic_or(CPUSTAT_STOP_INT, li->cpuflags);
13791379 break;
13801380 case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
1381− atomic_set_mask(CPUSTAT_IO_INT, li->cpuflags);
1381+ atomic_or(CPUSTAT_IO_INT, li->cpuflags);
13821382 break;
13831383 default:
1384− atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
1384+ atomic_or(CPUSTAT_EXT_INT, li->cpuflags);
13851385 break;
13861386 }
13871387 spin_unlock(&li->lock);
arch/s390/kvm/kvm-s390.c+16−16
@@ -1333,12 +1333,12 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) · 1332 unmodified lines
13331333 save_access_regs(vcpu->arch.host_acrs);
13341334 restore_access_regs(vcpu->run->s.regs.acrs);
13351335 gmap_enable(vcpu->arch.gmap);
1336− atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
1336+ atomic_or(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
13371337 }
13381338
13391339 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
13401340 {
1341− atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
1341+ atomic_andnot(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
13421342 gmap_disable(vcpu->arch.gmap);
13431343
13441344 save_fpu_regs();
@@ -1443,9 +1443,9 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) · 98 unmodified lines
14431443 CPUSTAT_STOPPED);
14441444
14451445 if (test_kvm_facility(vcpu->kvm, 78))
1446− atomic_set_mask(CPUSTAT_GED2, &vcpu->arch.sie_block->cpuflags);
1446+ atomic_or(CPUSTAT_GED2, &vcpu->arch.sie_block->cpuflags);
14471447 else if (test_kvm_facility(vcpu->kvm, 8))
1448− atomic_set_mask(CPUSTAT_GED, &vcpu->arch.sie_block->cpuflags);
1448+ atomic_or(CPUSTAT_GED, &vcpu->arch.sie_block->cpuflags);
14491449
14501450 kvm_s390_vcpu_setup_model(vcpu);
14511451
@@ -1557,24 +1557,24 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu) · 105 unmodified lines
15571557
15581558 void kvm_s390_vcpu_block(struct kvm_vcpu *vcpu)
15591559 {
1560− atomic_set_mask(PROG_BLOCK_SIE, &vcpu->arch.sie_block->prog20);
1560+ atomic_or(PROG_BLOCK_SIE, &vcpu->arch.sie_block->prog20);
15611561 exit_sie(vcpu);
15621562 }
15631563
15641564 void kvm_s390_vcpu_unblock(struct kvm_vcpu *vcpu)
15651565 {
1566− atomic_clear_mask(PROG_BLOCK_SIE, &vcpu->arch.sie_block->prog20);
1566+ atomic_andnot(PROG_BLOCK_SIE, &vcpu->arch.sie_block->prog20);
15671567 }
15681568
15691569 static void kvm_s390_vcpu_request(struct kvm_vcpu *vcpu)
15701570 {
1571− atomic_set_mask(PROG_REQUEST, &vcpu->arch.sie_block->prog20);
1571+ atomic_or(PROG_REQUEST, &vcpu->arch.sie_block->prog20);
15721572 exit_sie(vcpu);
15731573 }
15741574
15751575 static void kvm_s390_vcpu_request_handled(struct kvm_vcpu *vcpu)
15761576 {
1577− atomic_clear_mask(PROG_REQUEST, &vcpu->arch.sie_block->prog20);
1577+ atomic_or(PROG_REQUEST, &vcpu->arch.sie_block->prog20);
15781578 }
15791579
15801580 /*
@@ -1583,7 +1583,7 @@ static void kvm_s390_vcpu_request_handled(struct kvm_vcpu *vcpu) · 2 unmodified lines
15831583 * return immediately. */
15841584 void exit_sie(struct kvm_vcpu *vcpu)
15851585 {
1586− atomic_set_mask(CPUSTAT_STOP_INT, &vcpu->arch.sie_block->cpuflags);
1586+ atomic_or(CPUSTAT_STOP_INT, &vcpu->arch.sie_block->cpuflags);
15871587 while (vcpu->arch.sie_block->prog0c & PROG_IN_SIE)
15881588 cpu_relax();
15891589 }
@@ -1807,19 +1807,19 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, · 217 unmodified lines
18071807 if (dbg->control & KVM_GUESTDBG_ENABLE) {
18081808 vcpu->guest_debug = dbg->control;
18091809 /* enforce guest PER */
1810− atomic_set_mask(CPUSTAT_P, &vcpu->arch.sie_block->cpuflags);
1810+ atomic_or(CPUSTAT_P, &vcpu->arch.sie_block->cpuflags);
18111811
18121812 if (dbg->control & KVM_GUESTDBG_USE_HW_BP)
18131813 rc = kvm_s390_import_bp_data(vcpu, dbg);
18141814 } else {
1815− atomic_clear_mask(CPUSTAT_P, &vcpu->arch.sie_block->cpuflags);
1815+ atomic_andnot(CPUSTAT_P, &vcpu->arch.sie_block->cpuflags);
18161816 vcpu->arch.guestdbg.last_bp = 0;
18171817 }
18181818
18191819 if (rc) {
18201820 vcpu->guest_debug = 0;
18211821 kvm_s390_clear_bp_data(vcpu);
1822− atomic_clear_mask(CPUSTAT_P, &vcpu->arch.sie_block->cpuflags);
1822+ atomic_andnot(CPUSTAT_P, &vcpu->arch.sie_block->cpuflags);
18231823 }
18241824
18251825 return rc;
@@ -1894,7 +1894,7 @@ retry: · 68 unmodified lines
18941894 if (kvm_check_request(KVM_REQ_ENABLE_IBS, vcpu)) {
18951895 if (!ibs_enabled(vcpu)) {
18961896 trace_kvm_s390_enable_disable_ibs(vcpu->vcpu_id, 1);
1897− atomic_set_mask(CPUSTAT_IBS,
1897+ atomic_or(CPUSTAT_IBS,
18981898 &vcpu->arch.sie_block->cpuflags);
18991899 }
19001900 goto retry;
@@ -1903,7 +1903,7 @@ retry: · 2 unmodified lines
19031903 if (kvm_check_request(KVM_REQ_DISABLE_IBS, vcpu)) {
19041904 if (ibs_enabled(vcpu)) {
19051905 trace_kvm_s390_enable_disable_ibs(vcpu->vcpu_id, 0);
1906− atomic_clear_mask(CPUSTAT_IBS,
1906+ atomic_andnot(CPUSTAT_IBS,
19071907 &vcpu->arch.sie_block->cpuflags);
19081908 }
19091909 goto retry;
@@ -2419,7 +2419,7 @@ void kvm_s390_vcpu_start(struct kvm_vcpu *vcpu) · 509 unmodified lines
24192419 __disable_ibs_on_all_vcpus(vcpu->kvm);
24202420 }
24212421
2422− atomic_clear_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
2422+ atomic_andnot(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
24232423 /*
24242424 * Another VCPU might have used IBS while we were offline.
24252425 * Let's play safe and flush the VCPU at startup.
@@ -2445,7 +2445,7 @@ void kvm_s390_vcpu_stop(struct kvm_vcpu *vcpu) · 19 unmodified lines
24452445 /* SIGP STOP and SIGP STOP AND STORE STATUS has been fully processed */
24462446 kvm_s390_clear_stop_irq(vcpu);
24472447
2448− atomic_set_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
2448+ atomic_or(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
24492449 __disable_ibs_on_vcpu(vcpu);
24502450
24512451 for (i = 0; i < online_vcpus; i++) {
arch/s390/lib/uaccess.c+6−6
@@ -15,7 +15,7 @@ · 14 unmodified lines
1515 #include <asm/mmu_context.h>
1616 #include <asm/facility.h>
1717
18−static struct static_key have_mvcos = STATIC_KEY_INIT_FALSE;
18+static DEFINE_STATIC_KEY_FALSE(have_mvcos);
1919
2020 static inline unsigned long copy_from_user_mvcos(void *x, const void __user *ptr,
2121 unsigned long size)
@@ -104,7 +104,7 @@ static inline unsigned long copy_from_user_mvcp(void *x, const void __user *ptr, · 82 unmodified lines
104104
105105 unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n)
106106 {
107− if (static_key_false(&have_mvcos))
107+ if (static_branch_likely(&have_mvcos))
108108 return copy_from_user_mvcos(to, from, n);
109109 return copy_from_user_mvcp(to, from, n);
110110 }
@@ -177,7 +177,7 @@ static inline unsigned long copy_to_user_mvcs(void __user *ptr, const void *x, · 66 unmodified lines
177177
178178 unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n)
179179 {
180− if (static_key_false(&have_mvcos))
180+ if (static_branch_likely(&have_mvcos))
181181 return copy_to_user_mvcos(to, from, n);
182182 return copy_to_user_mvcs(to, from, n);
183183 }
@@ -240,7 +240,7 @@ static inline unsigned long copy_in_user_mvc(void __user *to, const void __user · 56 unmodified lines
240240
241241 unsigned long __copy_in_user(void __user *to, const void __user *from, unsigned long n)
242242 {
243− if (static_key_false(&have_mvcos))
243+ if (static_branch_likely(&have_mvcos))
244244 return copy_in_user_mvcos(to, from, n);
245245 return copy_in_user_mvc(to, from, n);
246246 }
@@ -312,7 +312,7 @@ static inline unsigned long clear_user_xc(void __user *to, unsigned long size) · 65 unmodified lines
312312
313313 unsigned long __clear_user(void __user *to, unsigned long size)
314314 {
315− if (static_key_false(&have_mvcos))
315+ if (static_branch_likely(&have_mvcos))
316316 return clear_user_mvcos(to, size);
317317 return clear_user_xc(to, size);
318318 }
@@ -373,7 +373,7 @@ EXPORT_SYMBOL(__strncpy_from_user); · 54 unmodified lines
373373 static int __init uaccess_init(void)
374374 {
375375 if (test_facility(27))
376− static_key_slow_inc(&have_mvcos);
376+ static_branch_enable(&have_mvcos);
377377 return 0;
378378 }
379379 early_initcall(uaccess_init);
arch/sh/include/asm/atomic-grb.h+4−39
@@ -48,47 +48,12 @@ static inline int atomic_##op##_return(int i, atomic_t *v) \ · 47 unmodified lines
4848 ATOMIC_OPS(add)
4949 ATOMIC_OPS(sub)
5050
51+ATOMIC_OP(and)
52+ATOMIC_OP(or)
53+ATOMIC_OP(xor)
54+
5155 #undef ATOMIC_OPS
5256 #undef ATOMIC_OP_RETURN
5357 #undef ATOMIC_OP
5458
55−static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
56−{
57− int tmp;
58− unsigned int _mask = ~mask;
59−
60− __asm__ __volatile__ (
61− " .align 2 \n\t"
62− " mova 1f, r0 \n\t" /* r0 = end point */
63− " mov r15, r1 \n\t" /* r1 = saved sp */
64− " mov #-6, r15 \n\t" /* LOGIN: r15 = size */
65− " mov.l @%1, %0 \n\t" /* load old value */
66− " and %2, %0 \n\t" /* add */
67− " mov.l %0, @%1 \n\t" /* store new value */
68− "1: mov r1, r15 \n\t" /* LOGOUT */
69− : "=&r" (tmp),
70− "+r" (v)
71− : "r" (_mask)
72− : "memory" , "r0", "r1");
73−}
74−
75−static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
76−{
77− int tmp;
78−
79− __asm__ __volatile__ (
80− " .align 2 \n\t"
81− " mova 1f, r0 \n\t" /* r0 = end point */
82− " mov r15, r1 \n\t" /* r1 = saved sp */
83− " mov #-6, r15 \n\t" /* LOGIN: r15 = size */
84− " mov.l @%1, %0 \n\t" /* load old value */
85− " or %2, %0 \n\t" /* or */
86− " mov.l %0, @%1 \n\t" /* store new value */
87− "1: mov r1, r15 \n\t" /* LOGOUT */
88− : "=&r" (tmp),
89− "+r" (v)
90− : "r" (mask)
91− : "memory" , "r0", "r1");
92−}
93−
9459 #endif /* __ASM_SH_ATOMIC_GRB_H */
arch/sh/include/asm/atomic-irq.h+3−18
@@ -37,27 +37,12 @@ static inline int atomic_##op##_return(int i, atomic_t *v) \ · 36 unmodified lines
3737
3838 ATOMIC_OPS(add, +=)
3939 ATOMIC_OPS(sub, -=)
40+ATOMIC_OP(and, &=)
41+ATOMIC_OP(or, |=)
42+ATOMIC_OP(xor, ^=)
4043
4144 #undef ATOMIC_OPS
4245 #undef ATOMIC_OP_RETURN
4346 #undef ATOMIC_OP
4447
45−static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
46−{
47− unsigned long flags;
48−
49− raw_local_irq_save(flags);
50− v->counter &= ~mask;
51− raw_local_irq_restore(flags);
52−}
53−
54−static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
55−{
56− unsigned long flags;
57−
58− raw_local_irq_save(flags);
59− v->counter |= mask;
60− raw_local_irq_restore(flags);
61−}
62−
6348 #endif /* __ASM_SH_ATOMIC_IRQ_H */
arch/sh/include/asm/atomic-llsc.h+3−28
@@ -52,37 +52,12 @@ static inline int atomic_##op##_return(int i, atomic_t *v) \ · 51 unmodified lines
5252
5353 ATOMIC_OPS(add)
5454 ATOMIC_OPS(sub)
55+ATOMIC_OP(and)
56+ATOMIC_OP(or)
57+ATOMIC_OP(xor)
5558
5659 #undef ATOMIC_OPS
5760 #undef ATOMIC_OP_RETURN
5861 #undef ATOMIC_OP
5962
60−static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
61−{
62− unsigned long tmp;
63−
64− __asm__ __volatile__ (
65−"1: movli.l @%2, %0 ! atomic_clear_mask \n"
66−" and %1, %0 \n"
67−" movco.l %0, @%2 \n"
68−" bf 1b \n"
69− : "=&z" (tmp)
70− : "r" (~mask), "r" (&v->counter)
71− : "t");
72−}
73−
74−static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
75−{
76− unsigned long tmp;
77−
78− __asm__ __volatile__ (
79−"1: movli.l @%2, %0 ! atomic_set_mask \n"
80−" or %1, %0 \n"
81−" movco.l %0, @%2 \n"
82−" bf 1b \n"
83− : "=&z" (tmp)
84− : "r" (mask), "r" (&v->counter)
85− : "t");
86−}
87−
8863 #endif /* __ASM_SH_ATOMIC_LLSC_H */
arch/sparc/include/asm/atomic_32.h+3−1
@@ -17,10 +17,12 @@ · 16 unmodified lines
1717 #include <asm/barrier.h>
1818 #include <asm-generic/atomic64.h>
1919
20−
2120 #define ATOMIC_INIT(i) { (i) }
2221
2322 int atomic_add_return(int, atomic_t *);
23+void atomic_and(int, atomic_t *);
24+void atomic_or(int, atomic_t *);
25+void atomic_xor(int, atomic_t *);
2426 int atomic_cmpxchg(atomic_t *, int, int);
2527 int atomic_xchg(atomic_t *, int);
2628 int __atomic_add_unless(atomic_t *, int, int);
arch/sparc/include/asm/atomic_64.h+4−0
@@ -33,6 +33,10 @@ long atomic64_##op##_return(long, atomic64_t *); · 32 unmodified lines
3333 ATOMIC_OPS(add)
3434 ATOMIC_OPS(sub)
3535
36+ATOMIC_OP(and)
37+ATOMIC_OP(or)
38+ATOMIC_OP(xor)
39+
3640 #undef ATOMIC_OPS
3741 #undef ATOMIC_OP_RETURN
3842 #undef ATOMIC_OP
arch/sparc/include/asm/barrier_64.h+2−2
@@ -60,12 +60,12 @@ do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \ · 59 unmodified lines
6060 do { \
6161 compiletime_assert_atomic_type(*p); \
6262 barrier(); \
63− ACCESS_ONCE(*p) = (v); \
63+ WRITE_ONCE(*p, v); \
6464 } while (0)
6565
6666 #define smp_load_acquire(p) \
6767 ({ \
68− typeof(*p) ___p1 = ACCESS_ONCE(*p); \
68+ typeof(*p) ___p1 = READ_ONCE(*p); \
6969 compiletime_assert_atomic_type(*p); \
7070 barrier(); \
7171 ___p1; \
arch/sparc/include/asm/jump_label.h+26−9
@@ -7,16 +7,33 @@ · 6 unmodified lines
77
88 #define JUMP_LABEL_NOP_SIZE 4
99
10−static __always_inline bool arch_static_branch(struct static_key *key)
10+static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
1111 {
12− asm_volatile_goto("1:\n\t"
13− "nop\n\t"
14− "nop\n\t"
15− ".pushsection __jump_table, \"aw\"\n\t"
16− ".align 4\n\t"
17− ".word 1b, %l[l_yes], %c0\n\t"
18− ".popsection \n\t"
19− : : "i" (key) : : l_yes);
12+ asm_volatile_goto("1:\n\t"
13+ "nop\n\t"
14+ "nop\n\t"
15+ ".pushsection __jump_table, \"aw\"\n\t"
16+ ".align 4\n\t"
17+ ".word 1b, %l[l_yes], %c0\n\t"
18+ ".popsection \n\t"
19+ : : "i" (&((char *)key)[branch]) : : l_yes);
20+
21+ return false;
22+l_yes:
23+ return true;
24+}
25+
26+static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
27+{
28+ asm_volatile_goto("1:\n\t"
29+ "b %l[l_yes]\n\t"
30+ "nop\n\t"
31+ ".pushsection __jump_table, \"aw\"\n\t"
32+ ".align 4\n\t"
33+ ".word 1b, %l[l_yes], %c0\n\t"
34+ ".popsection \n\t"
35+ : : "i" (&((char *)key)[branch]) : : l_yes);
36+
2037 return false;
2138 l_yes:
2239 return true;
arch/sparc/kernel/jump_label.c+1−1
@@ -16,7 +16,7 @@ void arch_jump_label_transform(struct jump_entry *entry, · 15 unmodified lines
1616 u32 val;
1717 u32 *insn = (u32 *) (unsigned long) entry->code;
1818
19− if (type == JUMP_LABEL_ENABLE) {
19+ if (type == JUMP_LABEL_JMP) {
2020 s32 off = (s32)entry->target - (s32)entry->code;
2121
2222 #ifdef CONFIG_SPARC64
arch/sparc/lib/atomic32.c+19−3
@@ -27,22 +27,38 @@ static DEFINE_SPINLOCK(dummy); · 26 unmodified lines
2727
2828 #endif /* SMP */
2929
30−#define ATOMIC_OP(op, cop) \
30+#define ATOMIC_OP_RETURN(op, c_op) \
3131 int atomic_##op##_return(int i, atomic_t *v) \
3232 { \
3333 int ret; \
3434 unsigned long flags; \
3535 spin_lock_irqsave(ATOMIC_HASH(v), flags); \
3636 \
37− ret = (v->counter cop i); \
37+ ret = (v->counter c_op i); \
3838 \
3939 spin_unlock_irqrestore(ATOMIC_HASH(v), flags); \
4040 return ret; \
4141 } \
4242 EXPORT_SYMBOL(atomic_##op##_return);
4343
44−ATOMIC_OP(add, +=)
44+#define ATOMIC_OP(op, c_op) \
45+void atomic_##op(int i, atomic_t *v) \
46+{ \
47+ unsigned long flags; \
48+ spin_lock_irqsave(ATOMIC_HASH(v), flags); \
49+ \
50+ v->counter c_op i; \
51+ \
52+ spin_unlock_irqrestore(ATOMIC_HASH(v), flags); \
53+} \
54+EXPORT_SYMBOL(atomic_##op);
55+
56+ATOMIC_OP_RETURN(add, +=)
57+ATOMIC_OP(and, &=)
58+ATOMIC_OP(or, |=)
59+ATOMIC_OP(xor, ^=)
4560
61+#undef ATOMIC_OP_RETURN
4662 #undef ATOMIC_OP
4763
4864 int atomic_xchg(atomic_t *v, int new)
arch/sparc/lib/atomic_64.S+6−0
@@ -47,6 +47,9 @@ ENDPROC(atomic_##op##_return); · 46 unmodified lines
4747
4848 ATOMIC_OPS(add)
4949 ATOMIC_OPS(sub)
50+ATOMIC_OP(and)
51+ATOMIC_OP(or)
52+ATOMIC_OP(xor)
5053
5154 #undef ATOMIC_OPS
5255 #undef ATOMIC_OP_RETURN
@@ -84,6 +87,9 @@ ENDPROC(atomic64_##op##_return); · 31 unmodified lines
8487
8588 ATOMIC64_OPS(add)
8689 ATOMIC64_OPS(sub)
90+ATOMIC64_OP(and)
91+ATOMIC64_OP(or)
92+ATOMIC64_OP(xor)
8793
8894 #undef ATOMIC64_OPS
8995 #undef ATOMIC64_OP_RETURN
arch/sparc/lib/ksyms.c+3−0
@@ -111,6 +111,9 @@ EXPORT_SYMBOL(atomic64_##op##_return); · 110 unmodified lines
111111
112112 ATOMIC_OPS(add)
113113 ATOMIC_OPS(sub)
114+ATOMIC_OP(and)
115+ATOMIC_OP(or)
116+ATOMIC_OP(xor)
114117
115118 #undef ATOMIC_OPS
116119 #undef ATOMIC_OP_RETURN
arch/tile/include/asm/atomic_32.h+28−0
@@ -34,6 +34,19 @@ static inline void atomic_add(int i, atomic_t *v) · 33 unmodified lines
3434 _atomic_xchg_add(&v->counter, i);
3535 }
3636
37+#define ATOMIC_OP(op) \
38+unsigned long _atomic_##op(volatile unsigned long *p, unsigned long mask); \
39+static inline void atomic_##op(int i, atomic_t *v) \
40+{ \
41+ _atomic_##op((unsigned long *)&v->counter, i); \
42+}
43+
44+ATOMIC_OP(and)
45+ATOMIC_OP(or)
46+ATOMIC_OP(xor)
47+
48+#undef ATOMIC_OP
49+
3750 /**
3851 * atomic_add_return - add integer and return
3952 * @v: pointer of type atomic_t
@@ -113,6 +126,17 @@ static inline void atomic64_add(long long i, atomic64_t *v) · 73 unmodified lines
113126 _atomic64_xchg_add(&v->counter, i);
114127 }
115128
129+#define ATOMIC64_OP(op) \
130+long long _atomic64_##op(long long *v, long long n); \
131+static inline void atomic64_##op(long long i, atomic64_t *v) \
132+{ \
133+ _atomic64_##op(&v->counter, i); \
134+}
135+
136+ATOMIC64_OP(and)
137+ATOMIC64_OP(or)
138+ATOMIC64_OP(xor)
139+
116140 /**
117141 * atomic64_add_return - add integer and return
118142 * @v: pointer of type atomic64_t
@@ -225,6 +249,7 @@ extern struct __get_user __atomic_xchg_add(volatile int *p, int *lock, int n); · 106 unmodified lines
225249 extern struct __get_user __atomic_xchg_add_unless(volatile int *p,
226250 int *lock, int o, int n);
227251 extern struct __get_user __atomic_or(volatile int *p, int *lock, int n);
252+extern struct __get_user __atomic_and(volatile int *p, int *lock, int n);
228253 extern struct __get_user __atomic_andn(volatile int *p, int *lock, int n);
229254 extern struct __get_user __atomic_xor(volatile int *p, int *lock, int n);
230255 extern long long __atomic64_cmpxchg(volatile long long *p, int *lock,
@@ -234,6 +259,9 @@ extern long long __atomic64_xchg_add(volatile long long *p, int *lock, · 3 unmodified lines
234259 long long n);
235260 extern long long __atomic64_xchg_add_unless(volatile long long *p,
236261 int *lock, long long o, long long n);
262+extern long long __atomic64_and(volatile long long *p, int *lock, long long n);
263+extern long long __atomic64_or(volatile long long *p, int *lock, long long n);
264+extern long long __atomic64_xor(volatile long long *p, int *lock, long long n);
237265
238266 /* Return failure from the atomic wrappers. */
239267 struct __get_user __atomic_bad_address(int __user *addr);
arch/tile/include/asm/atomic_64.h+40−0
@@ -58,6 +58,26 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u) · 57 unmodified lines
5858 return oldval;
5959 }
6060
61+static inline void atomic_and(int i, atomic_t *v)
62+{
63+ __insn_fetchand4((void *)&v->counter, i);
64+}
65+
66+static inline void atomic_or(int i, atomic_t *v)
67+{
68+ __insn_fetchor4((void *)&v->counter, i);
69+}
70+
71+static inline void atomic_xor(int i, atomic_t *v)
72+{
73+ int guess, oldval = v->counter;
74+ do {
75+ guess = oldval;
76+ __insn_mtspr(SPR_CMPEXCH_VALUE, guess);
77+ oldval = __insn_cmpexch4(&v->counter, guess ^ i);
78+ } while (guess != oldval);
79+}
80+
6181 /* Now the true 64-bit operations. */
6282
6383 #define ATOMIC64_INIT(i) { (i) }
@@ -91,6 +111,26 @@ static inline long atomic64_add_unless(atomic64_t *v, long a, long u) · 27 unmodified lines
91111 return oldval != u;
92112 }
93113
114+static inline void atomic64_and(long i, atomic64_t *v)
115+{
116+ __insn_fetchand((void *)&v->counter, i);
117+}
118+
119+static inline void atomic64_or(long i, atomic64_t *v)
120+{
121+ __insn_fetchor((void *)&v->counter, i);
122+}
123+
124+static inline void atomic64_xor(long i, atomic64_t *v)
125+{
126+ long guess, oldval = v->counter;
127+ do {
128+ guess = oldval;
129+ __insn_mtspr(SPR_CMPEXCH_VALUE, guess);
130+ oldval = __insn_cmpexch(&v->counter, guess ^ i);
131+ } while (guess != oldval);
132+}
133+
94134 #define atomic64_sub_return(i, v) atomic64_add_return(-(i), (v))
95135 #define atomic64_sub(i, v) atomic64_add(-(i), (v))
96136 #define atomic64_inc_return(v) atomic64_add_return(1, (v))
arch/tile/lib/atomic_32.c+23−0
@@ -94,6 +94,12 @@ unsigned long _atomic_or(volatile unsigned long *p, unsigned long mask) · 93 unmodified lines
9494 }
9595 EXPORT_SYMBOL(_atomic_or);
9696
97+unsigned long _atomic_and(volatile unsigned long *p, unsigned long mask)
98+{
99+ return __atomic_and((int *)p, __atomic_setup(p), mask).val;
100+}
101+EXPORT_SYMBOL(_atomic_and);
102+
97103 unsigned long _atomic_andn(volatile unsigned long *p, unsigned long mask)
98104 {
99105 return __atomic_andn((int *)p, __atomic_setup(p), mask).val;
@@ -136,6 +142,23 @@ long long _atomic64_cmpxchg(long long *v, long long o, long long n) · 36 unmodified lines
136142 }
137143 EXPORT_SYMBOL(_atomic64_cmpxchg);
138144
145+long long _atomic64_and(long long *v, long long n)
146+{
147+ return __atomic64_and(v, __atomic_setup(v), n);
148+}
149+EXPORT_SYMBOL(_atomic64_and);
150+
151+long long _atomic64_or(long long *v, long long n)
152+{
153+ return __atomic64_or(v, __atomic_setup(v), n);
154+}
155+EXPORT_SYMBOL(_atomic64_or);
156+
157+long long _atomic64_xor(long long *v, long long n)
158+{
159+ return __atomic64_xor(v, __atomic_setup(v), n);
160+}
161+EXPORT_SYMBOL(_atomic64_xor);
139162
140163 /*
141164 * If any of the atomic or futex routines hit a bad address (not in
arch/tile/lib/atomic_asm_32.S+4−0
@@ -178,6 +178,7 @@ atomic_op _xchg_add, 32, "add r24, r22, r2" · 177 unmodified lines
178178 atomic_op _xchg_add_unless, 32, \
179179 "sne r26, r22, r2; { bbns r26, 3f; add r24, r22, r3 }"
180180 atomic_op _or, 32, "or r24, r22, r2"
181+atomic_op _and, 32, "and r24, r22, r2"
181182 atomic_op _andn, 32, "nor r2, r2, zero; and r24, r22, r2"
182183 atomic_op _xor, 32, "xor r24, r22, r2"
183184
@@ -191,6 +192,9 @@ atomic_op 64_xchg_add_unless, 64, \ · 7 unmodified lines
191192 { bbns r26, 3f; add r24, r22, r4 }; \
192193 { bbns r27, 3f; add r25, r23, r5 }; \
193194 slt_u r26, r24, r22; add r25, r25, r26"
195+atomic_op 64_or, 64, "{ or r24, r22, r2; or r25, r23, r3 }"
196+atomic_op 64_and, 64, "{ and r24, r22, r2; and r25, r23, r3 }"
197+atomic_op 64_xor, 64, "{ xor r24, r22, r2; xor r25, r23, r3 }"
194198
195199 jrp lr /* happy backtracer */
196200
arch/x86/include/asm/atomic.h+15−10
@@ -182,6 +182,21 @@ static inline int atomic_xchg(atomic_t *v, int new) · 181 unmodified lines
182182 return xchg(&v->counter, new);
183183 }
184184
185+#define ATOMIC_OP(op) \
186+static inline void atomic_##op(int i, atomic_t *v) \
187+{ \
188+ asm volatile(LOCK_PREFIX #op"l %1,%0" \
189+ : "+m" (v->counter) \
190+ : "ir" (i) \
191+ : "memory"); \
192+}
193+
194+ATOMIC_OP(and)
195+ATOMIC_OP(or)
196+ATOMIC_OP(xor)
197+
198+#undef ATOMIC_OP
199+
185200 /**
186201 * __atomic_add_unless - add unless the number is already a given value
187202 * @v: pointer of type atomic_t
@@ -219,16 +234,6 @@ static __always_inline short int atomic_inc_short(short int *v) · 31 unmodified lines
219234 return *v;
220235 }
221236
222−/* These are x86-specific, used by some header files */
223−#define atomic_clear_mask(mask, addr) \
224− asm volatile(LOCK_PREFIX "andl %0,%1" \
225− : : "r" (~(mask)), "m" (*(addr)) : "memory")
226−
227−#define atomic_set_mask(mask, addr) \
228− asm volatile(LOCK_PREFIX "orl %0,%1" \
229− : : "r" ((unsigned)(mask)), "m" (*(addr)) \
230− : "memory")
231−
232237 #ifdef CONFIG_X86_32
233238 # include <asm/atomic64_32.h>
234239 #else
arch/x86/include/asm/atomic64_32.h+14−0
@@ -313,4 +313,18 @@ static inline long long atomic64_dec_if_positive(atomic64_t *v) · 312 unmodified lines
313313 #undef alternative_atomic64
314314 #undef __alternative_atomic64
315315
316+#define ATOMIC64_OP(op, c_op) \
317+static inline void atomic64_##op(long long i, atomic64_t *v) \
318+{ \
319+ long long old, c = 0; \
320+ while ((old = atomic64_cmpxchg(v, c, c c_op i)) != c) \
321+ c = old; \
322+}
323+
324+ATOMIC64_OP(and, &)
325+ATOMIC64_OP(or, |)
326+ATOMIC64_OP(xor, ^)
327+
328+#undef ATOMIC64_OP
329+
316330 #endif /* _ASM_X86_ATOMIC64_32_H */
arch/x86/include/asm/atomic64_64.h+15−0
@@ -220,4 +220,19 @@ static inline long atomic64_dec_if_positive(atomic64_t *v) · 219 unmodified lines
220220 return dec;
221221 }
222222
223+#define ATOMIC64_OP(op) \
224+static inline void atomic64_##op(long i, atomic64_t *v) \
225+{ \
226+ asm volatile(LOCK_PREFIX #op"q %1,%0" \
227+ : "+m" (v->counter) \
228+ : "er" (i) \
229+ : "memory"); \
230+}
231+
232+ATOMIC64_OP(and)
233+ATOMIC64_OP(or)
234+ATOMIC64_OP(xor)
235+
236+#undef ATOMIC64_OP
237+
223238 #endif /* _ASM_X86_ATOMIC64_64_H */
arch/x86/include/asm/barrier.h+4−4
@@ -57,12 +57,12 @@ · 56 unmodified lines
5757 do { \
5858 compiletime_assert_atomic_type(*p); \
5959 smp_mb(); \
60− ACCESS_ONCE(*p) = (v); \
60+ WRITE_ONCE(*p, v); \
6161 } while (0)
6262
6363 #define smp_load_acquire(p) \
6464 ({ \
65− typeof(*p) ___p1 = ACCESS_ONCE(*p); \
65+ typeof(*p) ___p1 = READ_ONCE(*p); \
6666 compiletime_assert_atomic_type(*p); \
6767 smp_mb(); \
6868 ___p1; \
@@ -74,12 +74,12 @@ do { \ · 5 unmodified lines
7474 do { \
7575 compiletime_assert_atomic_type(*p); \
7676 barrier(); \
77− ACCESS_ONCE(*p) = (v); \
77+ WRITE_ONCE(*p, v); \
7878 } while (0)
7979
8080 #define smp_load_acquire(p) \
8181 ({ \
82− typeof(*p) ___p1 = ACCESS_ONCE(*p); \
82+ typeof(*p) ___p1 = READ_ONCE(*p); \
8383 compiletime_assert_atomic_type(*p); \
8484 barrier(); \
8585 ___p1; \
arch/x86/include/asm/jump_label.h+20−3
@@ -16,15 +16,32 @@ · 15 unmodified lines
1616 # define STATIC_KEY_INIT_NOP GENERIC_NOP5_ATOMIC
1717 #endif
1818
19−static __always_inline bool arch_static_branch(struct static_key *key)
19+static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
2020 {
2121 asm_volatile_goto("1:"
2222 ".byte " __stringify(STATIC_KEY_INIT_NOP) "\n\t"
2323 ".pushsection __jump_table, \"aw\" \n\t"
2424 _ASM_ALIGN "\n\t"
25− _ASM_PTR "1b, %l[l_yes], %c0 \n\t"
25+ _ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
2626 ".popsection \n\t"
27− : : "i" (key) : : l_yes);
27+ : : "i" (key), "i" (branch) : : l_yes);
28+
29+ return false;
30+l_yes:
31+ return true;
32+}
33+
34+static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
35+{
36+ asm_volatile_goto("1:"
37+ ".byte 0xe9\n\t .long %l[l_yes] - 2f\n\t"
38+ "2:\n\t"
39+ ".pushsection __jump_table, \"aw\" \n\t"
40+ _ASM_ALIGN "\n\t"
41+ _ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
42+ ".popsection \n\t"
43+ : : "i" (key), "i" (branch) : : l_yes);
44+
2845 return false;
2946 l_yes:
3047 return true;
arch/x86/include/asm/qrwlock.h+0−10
@@ -2,16 +2,6 @@ · 1 unmodified line
22 #define _ASM_X86_QRWLOCK_H
33
44 #include <asm-generic/qrwlock_types.h>
5−
6−#ifndef CONFIG_X86_PPRO_FENCE
7−#define queue_write_unlock queue_write_unlock
8−static inline void queue_write_unlock(struct qrwlock *lock)
9−{
10− barrier();
11− ACCESS_ONCE(*(u8 *)&lock->cnts) = 0;
12−}
13−#endif
14−
155 #include <asm-generic/qrwlock.h>
166
177 #endif /* _ASM_X86_QRWLOCK_H */
arch/x86/kernel/jump_label.c+1−1
@@ -45,7 +45,7 @@ static void __jump_label_transform(struct jump_entry *entry, · 44 unmodified lines
4545 const unsigned char default_nop[] = { STATIC_KEY_INIT_NOP };
4646 const unsigned char *ideal_nop = ideal_nops[NOP_ATOMIC5];
4747
48− if (type == JUMP_LABEL_ENABLE) {
48+ if (type == JUMP_LABEL_JMP) {
4949 if (init) {
5050 /*
5151 * Jump label is enabled for the first time.
arch/x86/kernel/tsc.c+10−12
@@ -38,7 +38,7 @@ static int __read_mostly tsc_unstable; · 37 unmodified lines
3838 erroneous rdtsc usage on !cpu_has_tsc processors */
3939 static int __read_mostly tsc_disabled = -1;
4040
41−static struct static_key __use_tsc = STATIC_KEY_INIT;
41+static DEFINE_STATIC_KEY_FALSE(__use_tsc);
4242
4343 int tsc_clocksource_reliable;
4444
@@ -274,7 +274,12 @@ done: · 229 unmodified lines
274274 */
275275 u64 native_sched_clock(void)
276276 {
277− u64 tsc_now;
277+ if (static_branch_likely(&__use_tsc)) {
278+ u64 tsc_now = rdtsc();
279+
280+ /* return the value in ns */
281+ return cycles_2_ns(tsc_now);
282+ }
278283
279284 /*
280285 * Fall back to jiffies if there's no TSC available:
@@ -284,16 +289,9 @@ u64 native_sched_clock(void) · 3 unmodified lines
284289 * very important for it to be as fast as the platform
285290 * can achieve it. )
286291 */
287− if (!static_key_false(&__use_tsc)) {
288− /* No locking but a rare wrong value is not a big deal: */
289− return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ);
290− }
291−
292− /* read the Time Stamp Counter: */
293− tsc_now = rdtsc();
294292
295− /* return the value in ns */
296− return cycles_2_ns(tsc_now);
293+ /* No locking but a rare wrong value is not a big deal: */
294+ return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ);
297295 }
298296
299297 /*
@@ -1212,7 +1210,7 @@ void __init tsc_init(void) · 912 unmodified lines
12121210 /* now allow native_sched_clock() to use rdtsc */
12131211
12141212 tsc_disabled = 0;
1215− static_key_slow_inc(&__use_tsc);
1213+ static_branch_enable(&__use_tsc);
12161214
12171215 if (!no_sched_irq_time)
12181216 enable_sched_clock_irqtime();
arch/xtensa/configs/iss_defconfig+0−1
@@ -616,7 +616,6 @@ CONFIG_SCHED_DEBUG=y · 615 unmodified lines
616616 # CONFIG_SLUB_DEBUG_ON is not set
617617 # CONFIG_SLUB_STATS is not set
618618 # CONFIG_DEBUG_RT_MUTEXES is not set
619−# CONFIG_RT_MUTEX_TESTER is not set
620619 # CONFIG_DEBUG_SPINLOCK is not set
621620 # CONFIG_DEBUG_MUTEXES is not set
622621 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
arch/xtensa/include/asm/atomic.h+4−69
@@ -145,6 +145,10 @@ static inline int atomic_##op##_return(int i, atomic_t * v) \ · 144 unmodified lines
145145 ATOMIC_OPS(add)
146146 ATOMIC_OPS(sub)
147147
148+ATOMIC_OP(and)
149+ATOMIC_OP(or)
150+ATOMIC_OP(xor)
151+
148152 #undef ATOMIC_OPS
149153 #undef ATOMIC_OP_RETURN
150154 #undef ATOMIC_OP
@@ -250,75 +254,6 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) · 99 unmodified lines
250254 return c;
251255 }
252256
253−
254−static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
255−{
256−#if XCHAL_HAVE_S32C1I
257− unsigned long tmp;
258− int result;
259−
260− __asm__ __volatile__(
261− "1: l32i %1, %3, 0\n"
262− " wsr %1, scompare1\n"
263− " and %0, %1, %2\n"
264− " s32c1i %0, %3, 0\n"
265− " bne %0, %1, 1b\n"
266− : "=&a" (result), "=&a" (tmp)
267− : "a" (~mask), "a" (v)
268− : "memory"
269− );
270−#else
271− unsigned int all_f = -1;
272− unsigned int vval;
273−
274− __asm__ __volatile__(
275− " rsil a15,"__stringify(TOPLEVEL)"\n"
276− " l32i %0, %2, 0\n"
277− " xor %1, %4, %3\n"
278− " and %0, %0, %4\n"
279− " s32i %0, %2, 0\n"
280− " wsr a15, ps\n"
281− " rsync\n"
282− : "=&a" (vval), "=a" (mask)
283− : "a" (v), "a" (all_f), "1" (mask)
284− : "a15", "memory"
285− );
286−#endif
287−}
288−
289−static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
290−{
291−#if XCHAL_HAVE_S32C1I
292− unsigned long tmp;
293− int result;
294−
295− __asm__ __volatile__(
296− "1: l32i %1, %3, 0\n"
297− " wsr %1, scompare1\n"
298− " or %0, %1, %2\n"
299− " s32c1i %0, %3, 0\n"
300− " bne %0, %1, 1b\n"
301− : "=&a" (result), "=&a" (tmp)
302− : "a" (mask), "a" (v)
303− : "memory"
304− );
305−#else
306− unsigned int vval;
307−
308− __asm__ __volatile__(
309− " rsil a15,"__stringify(TOPLEVEL)"\n"
310− " l32i %0, %2, 0\n"
311− " or %0, %0, %1\n"
312− " s32i %0, %2, 0\n"
313− " wsr a15, ps\n"
314− " rsync\n"
315− : "=&a" (vval)
316− : "a" (mask), "a" (v)
317− : "a15", "memory"
318− );
319−#endif
320−}
321−
322257 #endif /* __KERNEL__ */
323258
324259 #endif /* _XTENSA_ATOMIC_H */
drivers/gpu/drm/i915/i915_drv.c+1−1
@@ -748,7 +748,7 @@ static int i915_drm_resume(struct drm_device *dev) · 747 unmodified lines
748748 mutex_lock(&dev->struct_mutex);
749749 if (i915_gem_init_hw(dev)) {
750750 DRM_ERROR("failed to re-initialize GPU, declaring wedged!\n");
751− atomic_set_mask(I915_WEDGED, &dev_priv->gpu_error.reset_counter);
751+ atomic_or(I915_WEDGED, &dev_priv->gpu_error.reset_counter);
752752 }
753753 mutex_unlock(&dev->struct_mutex);
754754
drivers/gpu/drm/i915/i915_gem.c+1−1
@@ -5091,7 +5091,7 @@ int i915_gem_init(struct drm_device *dev) · 5090 unmodified lines
50915091 * for all other failure, such as an allocation failure, bail.
50925092 */
50935093 DRM_ERROR("Failed to initialize GPU, declaring it wedged\n");
5094− atomic_set_mask(I915_WEDGED, &dev_priv->gpu_error.reset_counter);
5094+ atomic_or(I915_WEDGED, &dev_priv->gpu_error.reset_counter);
50955095 ret = 0;
50965096 }
50975097
drivers/gpu/drm/i915/i915_irq.c+2−2
@@ -2446,7 +2446,7 @@ static void i915_reset_and_wakeup(struct drm_device *dev) · 2445 unmodified lines
24462446 kobject_uevent_env(&dev->primary->kdev->kobj,
24472447 KOBJ_CHANGE, reset_done_event);
24482448 } else {
2449− atomic_set_mask(I915_WEDGED, &error->reset_counter);
2449+ atomic_or(I915_WEDGED, &error->reset_counter);
24502450 }
24512451
24522452 /*
@@ -2574,7 +2574,7 @@ void i915_handle_error(struct drm_device *dev, bool wedged, · 121 unmodified lines
25742574 i915_report_and_clear_eir(dev);
25752575
25762576 if (wedged) {
2577− atomic_set_mask(I915_RESET_IN_PROGRESS_FLAG,
2577+ atomic_or(I915_RESET_IN_PROGRESS_FLAG,
25782578 &dev_priv->gpu_error.reset_counter);
25792579
25802580 /*
drivers/s390/scsi/zfcp_aux.c+1−1
@@ -529,7 +529,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, · 528 unmodified lines
529529 list_add_tail(&port->list, &adapter->port_list);
530530 write_unlock_irq(&adapter->port_list_lock);
531531
532− atomic_set_mask(status | ZFCP_STATUS_COMMON_RUNNING, &port->status);
532+ atomic_or(status | ZFCP_STATUS_COMMON_RUNNING, &port->status);
533533
534534 return port;
535535
drivers/s390/scsi/zfcp_erp.c+31−31
@@ -190,7 +190,7 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status, · 189 unmodified lines
190190 if (!(act_status & ZFCP_STATUS_ERP_NO_REF))
191191 if (scsi_device_get(sdev))
192192 return NULL;
193− atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
193+ atomic_or(ZFCP_STATUS_COMMON_ERP_INUSE,
194194 &zfcp_sdev->status);
195195 erp_action = &zfcp_sdev->erp_action;
196196 memset(erp_action, 0, sizeof(struct zfcp_erp_action));
@@ -206,7 +206,7 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status, · 9 unmodified lines
206206 if (!get_device(&port->dev))
207207 return NULL;
208208 zfcp_erp_action_dismiss_port(port);
209− atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status);
209+ atomic_or(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status);
210210 erp_action = &port->erp_action;
211211 memset(erp_action, 0, sizeof(struct zfcp_erp_action));
212212 erp_action->port = port;
@@ -217,7 +217,7 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status, · 4 unmodified lines
217217 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
218218 kref_get(&adapter->ref);
219219 zfcp_erp_action_dismiss_adapter(adapter);
220− atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status);
220+ atomic_or(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status);
221221 erp_action = &adapter->erp_action;
222222 memset(erp_action, 0, sizeof(struct zfcp_erp_action));
223223 if (!(atomic_read(&adapter->status) &
@@ -254,7 +254,7 @@ static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter, · 30 unmodified lines
254254 act = zfcp_erp_setup_act(need, act_status, adapter, port, sdev);
255255 if (!act)
256256 goto out;
257− atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status);
257+ atomic_or(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status);
258258 ++adapter->erp_total_count;
259259 list_add_tail(&act->list, &adapter->erp_ready_head);
260260 wake_up(&adapter->erp_ready_wq);
@@ -486,14 +486,14 @@ static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter) · 225 unmodified lines
486486 {
487487 if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status))
488488 zfcp_dbf_rec_run("eraubl1", &adapter->erp_action);
489− atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status);
489+ atomic_or(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status);
490490 }
491491
492492 static void zfcp_erp_port_unblock(struct zfcp_port *port)
493493 {
494494 if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status))
495495 zfcp_dbf_rec_run("erpubl1", &port->erp_action);
496− atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status);
496+ atomic_or(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status);
497497 }
498498
499499 static void zfcp_erp_lun_unblock(struct scsi_device *sdev)
@@ -502,7 +502,7 @@ static void zfcp_erp_lun_unblock(struct scsi_device *sdev) · 2 unmodified lines
502502
503503 if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status))
504504 zfcp_dbf_rec_run("erlubl1", &sdev_to_zfcp(sdev)->erp_action);
505− atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status);
505+ atomic_or(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status);
506506 }
507507
508508 static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
@@ -642,7 +642,7 @@ static void zfcp_erp_wakeup(struct zfcp_adapter *adapter) · 133 unmodified lines
642642 read_lock_irqsave(&adapter->erp_lock, flags);
643643 if (list_empty(&adapter->erp_ready_head) &&
644644 list_empty(&adapter->erp_running_head)) {
645− atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING,
645+ atomic_andnot(ZFCP_STATUS_ADAPTER_ERP_PENDING,
646646 &adapter->status);
647647 wake_up(&adapter->erp_done_wqh);
648648 }
@@ -665,16 +665,16 @@ static int zfcp_erp_adapter_strat_fsf_xconf(struct zfcp_erp_action *erp_action) · 16 unmodified lines
665665 int sleep = 1;
666666 struct zfcp_adapter *adapter = erp_action->adapter;
667667
668− atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status);
668+ atomic_andnot(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status);
669669
670670 for (retries = 7; retries; retries--) {
671− atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
671+ atomic_andnot(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
672672 &adapter->status);
673673 write_lock_irq(&adapter->erp_lock);
674674 zfcp_erp_action_to_running(erp_action);
675675 write_unlock_irq(&adapter->erp_lock);
676676 if (zfcp_fsf_exchange_config_data(erp_action)) {
677− atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
677+ atomic_andnot(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
678678 &adapter->status);
679679 return ZFCP_ERP_FAILED;
680680 }
@@ -692,7 +692,7 @@ static int zfcp_erp_adapter_strat_fsf_xconf(struct zfcp_erp_action *erp_action) · 11 unmodified lines
692692 sleep *= 2;
693693 }
694694
695− atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
695+ atomic_andnot(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
696696 &adapter->status);
697697
698698 if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_XCONFIG_OK))
@@ -764,7 +764,7 @@ static void zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *act) · 65 unmodified lines
764764 /* all ports and LUNs are closed */
765765 zfcp_erp_clear_adapter_status(adapter, ZFCP_STATUS_COMMON_OPEN);
766766
767− atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
767+ atomic_andnot(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
768768 ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
769769 }
770770
@@ -773,7 +773,7 @@ static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *act) · 2 unmodified lines
773773 struct zfcp_adapter *adapter = act->adapter;
774774
775775 if (zfcp_qdio_open(adapter->qdio)) {
776− atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
776+ atomic_andnot(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
777777 ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
778778 &adapter->status);
779779 return ZFCP_ERP_FAILED;
@@ -784,7 +784,7 @@ static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *act) · 4 unmodified lines
784784 return ZFCP_ERP_FAILED;
785785 }
786786
787− atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &adapter->status);
787+ atomic_or(ZFCP_STATUS_COMMON_OPEN, &adapter->status);
788788
789789 return ZFCP_ERP_SUCCEEDED;
790790 }
@@ -948,7 +948,7 @@ static void zfcp_erp_lun_strategy_clearstati(struct scsi_device *sdev) · 157 unmodified lines
948948 {
949949 struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
950950
951− atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED,
951+ atomic_andnot(ZFCP_STATUS_COMMON_ACCESS_DENIED,
952952 &zfcp_sdev->status);
953953 }
954954
@@ -1187,18 +1187,18 @@ static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) · 232 unmodified lines
11871187 switch (erp_action->action) {
11881188 case ZFCP_ERP_ACTION_REOPEN_LUN:
11891189 zfcp_sdev = sdev_to_zfcp(erp_action->sdev);
1190− atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
1190+ atomic_andnot(ZFCP_STATUS_COMMON_ERP_INUSE,
11911191 &zfcp_sdev->status);
11921192 break;
11931193
11941194 case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
11951195 case ZFCP_ERP_ACTION_REOPEN_PORT:
1196− atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
1196+ atomic_andnot(ZFCP_STATUS_COMMON_ERP_INUSE,
11971197 &erp_action->port->status);
11981198 break;
11991199
12001200 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
1201− atomic_clear_mask(ZFCP_STATUS_COMMON_ERP_INUSE,
1201+ atomic_andnot(ZFCP_STATUS_COMMON_ERP_INUSE,
12021202 &erp_action->adapter->status);
12031203 break;
12041204 }
@@ -1422,19 +1422,19 @@ void zfcp_erp_set_adapter_status(struct zfcp_adapter *adapter, u32 mask) · 217 unmodified lines
14221422 unsigned long flags;
14231423 u32 common_mask = mask & ZFCP_COMMON_FLAGS;
14241424
1425− atomic_set_mask(mask, &adapter->status);
1425+ atomic_or(mask, &adapter->status);
14261426
14271427 if (!common_mask)
14281428 return;
14291429
14301430 read_lock_irqsave(&adapter->port_list_lock, flags);
14311431 list_for_each_entry(port, &adapter->port_list, list)
1432− atomic_set_mask(common_mask, &port->status);
1432+ atomic_or(common_mask, &port->status);
14331433 read_unlock_irqrestore(&adapter->port_list_lock, flags);
14341434
14351435 spin_lock_irqsave(adapter->scsi_host->host_lock, flags);
14361436 __shost_for_each_device(sdev, adapter->scsi_host)
1437− atomic_set_mask(common_mask, &sdev_to_zfcp(sdev)->status);
1437+ atomic_or(common_mask, &sdev_to_zfcp(sdev)->status);
14381438 spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags);
14391439 }
14401440
@@ -1453,7 +1453,7 @@ void zfcp_erp_clear_adapter_status(struct zfcp_adapter *adapter, u32 mask) · 12 unmodified lines
14531453 u32 common_mask = mask & ZFCP_COMMON_FLAGS;
14541454 u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED;
14551455
1456− atomic_clear_mask(mask, &adapter->status);
1456+ atomic_andnot(mask, &adapter->status);
14571457
14581458 if (!common_mask)
14591459 return;
@@ -1463,7 +1463,7 @@ void zfcp_erp_clear_adapter_status(struct zfcp_adapter *adapter, u32 mask) · 3 unmodified lines
14631463
14641464 read_lock_irqsave(&adapter->port_list_lock, flags);
14651465 list_for_each_entry(port, &adapter->port_list, list) {
1466− atomic_clear_mask(common_mask, &port->status);
1466+ atomic_andnot(common_mask, &port->status);
14671467 if (clear_counter)
14681468 atomic_set(&port->erp_counter, 0);
14691469 }
@@ -1471,7 +1471,7 @@ void zfcp_erp_clear_adapter_status(struct zfcp_adapter *adapter, u32 mask) · 1 unmodified line
14711471
14721472 spin_lock_irqsave(adapter->scsi_host->host_lock, flags);
14731473 __shost_for_each_device(sdev, adapter->scsi_host) {
1474− atomic_clear_mask(common_mask, &sdev_to_zfcp(sdev)->status);
1474+ atomic_andnot(common_mask, &sdev_to_zfcp(sdev)->status);
14751475 if (clear_counter)
14761476 atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0);
14771477 }
@@ -1491,7 +1491,7 @@ void zfcp_erp_set_port_status(struct zfcp_port *port, u32 mask) · 13 unmodified lines
14911491 u32 common_mask = mask & ZFCP_COMMON_FLAGS;
14921492 unsigned long flags;
14931493
1494− atomic_set_mask(mask, &port->status);
1494+ atomic_or(mask, &port->status);
14951495
14961496 if (!common_mask)
14971497 return;
@@ -1499,7 +1499,7 @@ void zfcp_erp_set_port_status(struct zfcp_port *port, u32 mask) · 1 unmodified line
14991499 spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags);
15001500 __shost_for_each_device(sdev, port->adapter->scsi_host)
15011501 if (sdev_to_zfcp(sdev)->port == port)
1502− atomic_set_mask(common_mask,
1502+ atomic_or(common_mask,
15031503 &sdev_to_zfcp(sdev)->status);
15041504 spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags);
15051505 }
@@ -1518,7 +1518,7 @@ void zfcp_erp_clear_port_status(struct zfcp_port *port, u32 mask) · 12 unmodified lines
15181518 u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED;
15191519 unsigned long flags;
15201520
1521− atomic_clear_mask(mask, &port->status);
1521+ atomic_andnot(mask, &port->status);
15221522
15231523 if (!common_mask)
15241524 return;
@@ -1529,7 +1529,7 @@ void zfcp_erp_clear_port_status(struct zfcp_port *port, u32 mask) · 4 unmodified lines
15291529 spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags);
15301530 __shost_for_each_device(sdev, port->adapter->scsi_host)
15311531 if (sdev_to_zfcp(sdev)->port == port) {
1532− atomic_clear_mask(common_mask,
1532+ atomic_andnot(common_mask,
15331533 &sdev_to_zfcp(sdev)->status);
15341534 if (clear_counter)
15351535 atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0);
@@ -1546,7 +1546,7 @@ void zfcp_erp_set_lun_status(struct scsi_device *sdev, u32 mask) · 10 unmodified lines
15461546 {
15471547 struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
15481548
1549− atomic_set_mask(mask, &zfcp_sdev->status);
1549+ atomic_or(mask, &zfcp_sdev->status);
15501550 }
15511551
15521552 /**
@@ -1558,7 +1558,7 @@ void zfcp_erp_clear_lun_status(struct scsi_device *sdev, u32 mask) · 5 unmodified lines
15581558 {
15591559 struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
15601560
1561− atomic_clear_mask(mask, &zfcp_sdev->status);
1561+ atomic_andnot(mask, &zfcp_sdev->status);
15621562
15631563 if (mask & ZFCP_STATUS_COMMON_ERP_FAILED)
15641564 atomic_set(&zfcp_sdev->erp_counter, 0);
drivers/s390/scsi/zfcp_fc.c+4−4
@@ -508,7 +508,7 @@ static void zfcp_fc_adisc_handler(void *data) · 507 unmodified lines
508508 /* port is good, unblock rport without going through erp */
509509 zfcp_scsi_schedule_rport_register(port);
510510 out:
511− atomic_clear_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status);
511+ atomic_andnot(ZFCP_STATUS_PORT_LINK_TEST, &port->status);
512512 put_device(&port->dev);
513513 kmem_cache_free(zfcp_fc_req_cache, fc_req);
514514 }
@@ -564,14 +564,14 @@ void zfcp_fc_link_test_work(struct work_struct *work) · 49 unmodified lines
564564 if (atomic_read(&port->status) & ZFCP_STATUS_PORT_LINK_TEST)
565565 goto out;
566566
567− atomic_set_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status);
567+ atomic_or(ZFCP_STATUS_PORT_LINK_TEST, &port->status);
568568
569569 retval = zfcp_fc_adisc(port);
570570 if (retval == 0)
571571 return;
572572
573573 /* send of ADISC was not possible */
574− atomic_clear_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status);
574+ atomic_andnot(ZFCP_STATUS_PORT_LINK_TEST, &port->status);
575575 zfcp_erp_port_forced_reopen(port, 0, "fcltwk1");
576576
577577 out:
@@ -640,7 +640,7 @@ static void zfcp_fc_validate_port(struct zfcp_port *port, struct list_head *lh) · 62 unmodified lines
640640 if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC))
641641 return;
642642
643− atomic_clear_mask(ZFCP_STATUS_COMMON_NOESC, &port->status);
643+ atomic_andnot(ZFCP_STATUS_COMMON_NOESC, &port->status);
644644
645645 if ((port->supported_classes != 0) ||
646646 !list_empty(&port->unit_list))
drivers/s390/scsi/zfcp_fsf.c+13−13
@@ -114,7 +114,7 @@ static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, · 113 unmodified lines
114114 if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED)
115115 return;
116116
117− atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
117+ atomic_or(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
118118
119119 zfcp_scsi_schedule_rports_block(adapter);
120120
@@ -345,7 +345,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req) · 224 unmodified lines
345345 zfcp_erp_adapter_shutdown(adapter, 0, "fspse_3");
346346 break;
347347 case FSF_PROT_HOST_CONNECTION_INITIALIZING:
348− atomic_set_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
348+ atomic_or(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
349349 &adapter->status);
350350 break;
351351 case FSF_PROT_DUPLICATE_REQUEST_ID:
@@ -554,7 +554,7 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) · 202 unmodified lines
554554 zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh1");
555555 return;
556556 }
557− atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
557+ atomic_or(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
558558 &adapter->status);
559559 break;
560560 case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
@@ -567,7 +567,7 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) · 6 unmodified lines
567567
568568 /* avoids adapter shutdown to be able to recognize
569569 * events such as LINK UP */
570− atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
570+ atomic_or(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
571571 &adapter->status);
572572 zfcp_fsf_link_down_info_eval(req,
573573 &qtcb->header.fsf_status_qual.link_down_info);
@@ -1394,9 +1394,9 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) · 820 unmodified lines
13941394 break;
13951395 case FSF_GOOD:
13961396 port->handle = header->port_handle;
1397− atomic_set_mask(ZFCP_STATUS_COMMON_OPEN |
1397+ atomic_or(ZFCP_STATUS_COMMON_OPEN |
13981398 ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1399− atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED,
1399+ atomic_andnot(ZFCP_STATUS_COMMON_ACCESS_BOXED,
14001400 &port->status);
14011401 /* check whether D_ID has changed during open */
14021402 /*
@@ -1677,10 +1677,10 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req) · 274 unmodified lines
16771677 case FSF_PORT_BOXED:
16781678 /* can't use generic zfcp_erp_modify_port_status because
16791679 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port */
1680− atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1680+ atomic_andnot(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
16811681 shost_for_each_device(sdev, port->adapter->scsi_host)
16821682 if (sdev_to_zfcp(sdev)->port == port)
1683− atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
1683+ atomic_andnot(ZFCP_STATUS_COMMON_OPEN,
16841684 &sdev_to_zfcp(sdev)->status);
16851685 zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ACCESS_BOXED);
16861686 zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED,
@@ -1700,10 +1700,10 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req) · 13 unmodified lines
17001700 /* can't use generic zfcp_erp_modify_port_status because
17011701 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port
17021702 */
1703− atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
1703+ atomic_andnot(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
17041704 shost_for_each_device(sdev, port->adapter->scsi_host)
17051705 if (sdev_to_zfcp(sdev)->port == port)
1706− atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
1706+ atomic_andnot(ZFCP_STATUS_COMMON_OPEN,
17071707 &sdev_to_zfcp(sdev)->status);
17081708 break;
17091709 }
@@ -1766,7 +1766,7 @@ static void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req) · 56 unmodified lines
17661766
17671767 zfcp_sdev = sdev_to_zfcp(sdev);
17681768
1769− atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
1769+ atomic_andnot(ZFCP_STATUS_COMMON_ACCESS_DENIED |
17701770 ZFCP_STATUS_COMMON_ACCESS_BOXED,
17711771 &zfcp_sdev->status);
17721772
@@ -1822,7 +1822,7 @@ static void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req) · 49 unmodified lines
18221822
18231823 case FSF_GOOD:
18241824 zfcp_sdev->lun_handle = header->lun_handle;
1825− atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status);
1825+ atomic_or(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status);
18261826 break;
18271827 }
18281828 }
@@ -1913,7 +1913,7 @@ static void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req) · 84 unmodified lines
19131913 }
19141914 break;
19151915 case FSF_GOOD:
1916− atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status);
1916+ atomic_andnot(ZFCP_STATUS_COMMON_OPEN, &zfcp_sdev->status);
19171917 break;
19181918 }
19191919 }
drivers/s390/scsi/zfcp_qdio.c+7−7
@@ -349,7 +349,7 @@ void zfcp_qdio_close(struct zfcp_qdio *qdio) · 348 unmodified lines
349349
350350 /* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */
351351 spin_lock_irq(&qdio->req_q_lock);
352− atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
352+ atomic_andnot(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
353353 spin_unlock_irq(&qdio->req_q_lock);
354354
355355 wake_up(&qdio->req_q_wq);
@@ -384,7 +384,7 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio) · 28 unmodified lines
384384 if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)
385385 return -EIO;
386386
387− atomic_clear_mask(ZFCP_STATUS_ADAPTER_SIOSL_ISSUED,
387+ atomic_andnot(ZFCP_STATUS_ADAPTER_SIOSL_ISSUED,
388388 &qdio->adapter->status);
389389
390390 zfcp_qdio_setup_init_data(&init_data, qdio);
@@ -396,14 +396,14 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio) · 5 unmodified lines
396396 goto failed_qdio;
397397
398398 if (ssqd.qdioac2 & CHSC_AC2_DATA_DIV_ENABLED)
399− atomic_set_mask(ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED,
399+ atomic_or(ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED,
400400 &qdio->adapter->status);
401401
402402 if (ssqd.qdioac2 & CHSC_AC2_MULTI_BUFFER_ENABLED) {
403− atomic_set_mask(ZFCP_STATUS_ADAPTER_MB_ACT, &adapter->status);
403+ atomic_or(ZFCP_STATUS_ADAPTER_MB_ACT, &adapter->status);
404404 qdio->max_sbale_per_sbal = QDIO_MAX_ELEMENTS_PER_BUFFER;
405405 } else {
406− atomic_clear_mask(ZFCP_STATUS_ADAPTER_MB_ACT, &adapter->status);
406+ atomic_andnot(ZFCP_STATUS_ADAPTER_MB_ACT, &adapter->status);
407407 qdio->max_sbale_per_sbal = QDIO_MAX_ELEMENTS_PER_BUFFER - 1;
408408 }
409409
@@ -427,7 +427,7 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio) · 17 unmodified lines
427427 /* set index of first available SBALS / number of available SBALS */
428428 qdio->req_q_idx = 0;
429429 atomic_set(&qdio->req_q_free, QDIO_MAX_BUFFERS_PER_Q);
430− atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status);
430+ atomic_or(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status);
431431
432432 if (adapter->scsi_host) {
433433 adapter->scsi_host->sg_tablesize = qdio->max_sbale_per_req;
@@ -499,6 +499,6 @@ void zfcp_qdio_siosl(struct zfcp_adapter *adapter) · 65 unmodified lines
499499
500500 rc = ccw_device_siosl(adapter->ccw_device);
501501 if (!rc)
502− atomic_set_mask(ZFCP_STATUS_ADAPTER_SIOSL_ISSUED,
502+ atomic_or(ZFCP_STATUS_ADAPTER_SIOSL_ISSUED,
503503 &adapter->status);
504504 }
include/asm-generic/atomic-long.h+93−170
@@ -23,236 +23,159 @@ · 22 unmodified lines
2323 typedef atomic64_t atomic_long_t;
2424
2525 #define ATOMIC_LONG_INIT(i) ATOMIC64_INIT(i)
26+#define ATOMIC_LONG_PFX(x) atomic64 ## x
2627
27−static inline long atomic_long_read(atomic_long_t *l)
28−{
29− atomic64_t *v = (atomic64_t *)l;
30−
31− return (long)atomic64_read(v);
32−}
33−
34−static inline void atomic_long_set(atomic_long_t *l, long i)
35−{
36− atomic64_t *v = (atomic64_t *)l;
37−
38− atomic64_set(v, i);
39−}
40−
41−static inline void atomic_long_inc(atomic_long_t *l)
42−{
43− atomic64_t *v = (atomic64_t *)l;
44−
45− atomic64_inc(v);
46−}
47−
48−static inline void atomic_long_dec(atomic_long_t *l)
49−{
50− atomic64_t *v = (atomic64_t *)l;
51−
52− atomic64_dec(v);
53−}
54−
55−static inline void atomic_long_add(long i, atomic_long_t *l)
56−{
57− atomic64_t *v = (atomic64_t *)l;
58−
59− atomic64_add(i, v);
60−}
61−
62−static inline void atomic_long_sub(long i, atomic_long_t *l)
63−{
64− atomic64_t *v = (atomic64_t *)l;
65−
66− atomic64_sub(i, v);
67−}
68−
69−static inline int atomic_long_sub_and_test(long i, atomic_long_t *l)
70−{
71− atomic64_t *v = (atomic64_t *)l;
72−
73− return atomic64_sub_and_test(i, v);
74−}
75−
76−static inline int atomic_long_dec_and_test(atomic_long_t *l)
77−{
78− atomic64_t *v = (atomic64_t *)l;
79−
80− return atomic64_dec_and_test(v);
81−}
82−
83−static inline int atomic_long_inc_and_test(atomic_long_t *l)
84−{
85− atomic64_t *v = (atomic64_t *)l;
86−
87− return atomic64_inc_and_test(v);
88−}
89−
90−static inline int atomic_long_add_negative(long i, atomic_long_t *l)
91−{
92− atomic64_t *v = (atomic64_t *)l;
93−
94− return atomic64_add_negative(i, v);
95−}
96−
97−static inline long atomic_long_add_return(long i, atomic_long_t *l)
98−{
99− atomic64_t *v = (atomic64_t *)l;
100−
101− return (long)atomic64_add_return(i, v);
102−}
103−
104−static inline long atomic_long_sub_return(long i, atomic_long_t *l)
105−{
106− atomic64_t *v = (atomic64_t *)l;
107−
108− return (long)atomic64_sub_return(i, v);
109−}
110−
111−static inline long atomic_long_inc_return(atomic_long_t *l)
112−{
113− atomic64_t *v = (atomic64_t *)l;
114−
115− return (long)atomic64_inc_return(v);
116−}
117−
118−static inline long atomic_long_dec_return(atomic_long_t *l)
119−{
120− atomic64_t *v = (atomic64_t *)l;
121−
122− return (long)atomic64_dec_return(v);
123−}
124−
125−static inline long atomic_long_add_unless(atomic_long_t *l, long a, long u)
126−{
127− atomic64_t *v = (atomic64_t *)l;
128−
129− return (long)atomic64_add_unless(v, a, u);
130−}
131−
132−#define atomic_long_inc_not_zero(l) atomic64_inc_not_zero((atomic64_t *)(l))
133−
134−#define atomic_long_cmpxchg(l, old, new) \
135− (atomic64_cmpxchg((atomic64_t *)(l), (old), (new)))
136−#define atomic_long_xchg(v, new) \
137− (atomic64_xchg((atomic64_t *)(v), (new)))
138−
139−#else /* BITS_PER_LONG == 64 */
28+#else
14029
14130 typedef atomic_t atomic_long_t;
14231
14332 #define ATOMIC_LONG_INIT(i) ATOMIC_INIT(i)
144−static inline long atomic_long_read(atomic_long_t *l)
145−{
146− atomic_t *v = (atomic_t *)l;
147−
148− return (long)atomic_read(v);
149−}
150−
151−static inline void atomic_long_set(atomic_long_t *l, long i)
152−{
153− atomic_t *v = (atomic_t *)l;
154−
155− atomic_set(v, i);
156−}
33+#define ATOMIC_LONG_PFX(x) atomic ## x
34+
35+#endif
36+
37+#define ATOMIC_LONG_READ_OP(mo) \
38+static inline long atomic_long_read##mo(atomic_long_t *l) \
39+{ \
40+ ATOMIC_LONG_PFX(_t) *v = (ATOMIC_LONG_PFX(_t) *)l; \
41+ \
42+ return (long)ATOMIC_LONG_PFX(_read##mo)(v); \
43+}
44+ATOMIC_LONG_READ_OP()
45+ATOMIC_LONG_READ_OP(_acquire)
46+
47+#undef ATOMIC_LONG_READ_OP
48+
49+#define ATOMIC_LONG_SET_OP(mo) \
50+static inline void atomic_long_set##mo(atomic_long_t *l, long i) \
51+{ \
52+ ATOMIC_LONG_PFX(_t) *v = (ATOMIC_LONG_PFX(_t) *)l; \
53+ \
54+ ATOMIC_LONG_PFX(_set##mo)(v, i); \
55+}
56+ATOMIC_LONG_SET_OP()
57+ATOMIC_LONG_SET_OP(_release)
58+
59+#undef ATOMIC_LONG_SET_OP
60+
61+#define ATOMIC_LONG_ADD_SUB_OP(op, mo) \
62+static inline long \
63+atomic_long_##op##_return##mo(long i, atomic_long_t *l) \
64+{ \
65+ ATOMIC_LONG_PFX(_t) *v = (ATOMIC_LONG_PFX(_t) *)l; \
66+ \
67+ return (long)ATOMIC_LONG_PFX(_##op##_return##mo)(i, v); \
68+}
69+ATOMIC_LONG_ADD_SUB_OP(add,)
70+ATOMIC_LONG_ADD_SUB_OP(add, _relaxed)
71+ATOMIC_LONG_ADD_SUB_OP(add, _acquire)
72+ATOMIC_LONG_ADD_SUB_OP(add, _release)
73+ATOMIC_LONG_ADD_SUB_OP(sub,)
74+ATOMIC_LONG_ADD_SUB_OP(sub, _relaxed)
75+ATOMIC_LONG_ADD_SUB_OP(sub, _acquire)
76+ATOMIC_LONG_ADD_SUB_OP(sub, _release)
77+
78+#undef ATOMIC_LONG_ADD_SUB_OP
79+
80+#define atomic_long_cmpxchg_relaxed(l, old, new) \
81+ (ATOMIC_LONG_PFX(_cmpxchg_relaxed)((ATOMIC_LONG_PFX(_t) *)(l), \
82+ (old), (new)))
83+#define atomic_long_cmpxchg_acquire(l, old, new) \
84+ (ATOMIC_LONG_PFX(_cmpxchg_acquire)((ATOMIC_LONG_PFX(_t) *)(l), \
85+ (old), (new)))
86+#define atomic_long_cmpxchg_release(l, old, new) \
87+ (ATOMIC_LONG_PFX(_cmpxchg_release)((ATOMIC_LONG_PFX(_t) *)(l), \
88+ (old), (new)))
89+#define atomic_long_cmpxchg(l, old, new) \
90+ (ATOMIC_LONG_PFX(_cmpxchg)((ATOMIC_LONG_PFX(_t) *)(l), (old), (new)))
91+
92+#define atomic_long_xchg_relaxed(v, new) \
93+ (ATOMIC_LONG_PFX(_xchg_relaxed)((ATOMIC_LONG_PFX(_t) *)(v), (new)))
94+#define atomic_long_xchg_acquire(v, new) \
95+ (ATOMIC_LONG_PFX(_xchg_acquire)((ATOMIC_LONG_PFX(_t) *)(v), (new)))
96+#define atomic_long_xchg_release(v, new) \
97+ (ATOMIC_LONG_PFX(_xchg_release)((ATOMIC_LONG_PFX(_t) *)(v), (new)))
98+#define atomic_long_xchg(v, new) \
99+ (ATOMIC_LONG_PFX(_xchg)((ATOMIC_LONG_PFX(_t) *)(v), (new)))
157100
158101 static inline void atomic_long_inc(atomic_long_t *l)
159102 {
160− atomic_t *v = (atomic_t *)l;
103+ ATOMIC_LONG_PFX(_t) *v = (ATOMIC_LONG_PFX(_t) *)l;
161104
162− atomic_inc(v);
105+ ATOMIC_LONG_PFX(_inc)(v);
163106 }
164107
165108 static inline void atomic_long_dec(atomic_long_t *l)
166109 {
167− atomic_t *v = (atomic_t *)l;
110+ ATOMIC_LONG_PFX(_t) *v = (ATOMIC_LONG_PFX(_t) *)l;
168111
169− atomic_dec(v);
112+ ATOMIC_LONG_PFX(_dec)(v);
170113 }
171114
172115 static inline void atomic_long_add(long i, atomic_long_t *l)
173116 {
174− atomic_t *v = (atomic_t *)l;
117+ ATOMIC_LONG_PFX(_t) *v = (ATOMIC_LONG_PFX(_t) *)l;
175118
176− atomic_add(i, v);
119+ ATOMIC_LONG_PFX(_add)(i, v);
177120 }
178121
179122 static inline void atomic_long_sub(long i, atomic_long_t *l)
180123 {
181− atomic_t *v = (atomic_t *)l;
124+ ATOMIC_LONG_PFX(_t) *v = (ATOMIC_LONG_PFX(_t) *)l;
182125
183− atomic_sub(i, v);
126+ ATOMIC_LONG_PFX(_sub)(i, v);
184127 }
185128
186129 static inline int atomic_long_sub_and_test(long i, atomic_long_t *l)
187130 {
188− atomic_t *v = (atomic_t *)l;
131+ ATOMIC_LONG_PFX(_t) *v = (ATOMIC_LONG_PFX(_t) *)l;
189132
190− return atomic_sub_and_test(i, v);
133+ return ATOMIC_LONG_PFX(_sub_and_test)(i, v);
191134 }
192135
193136 static inline int atomic_long_dec_and_test(atomic_long_t *l)
194137 {
195− atomic_t *v = (atomic_t *)l;
138+ ATOMIC_LONG_PFX(_t) *v = (ATOMIC_LONG_PFX(_t) *)l;
196139
197− return atomic_dec_and_test(v);
140+ return ATOMIC_LONG_PFX(_dec_and_test)(v);
198141 }
199142
200143 static inline int atomic_long_inc_and_test(atomic_long_t *l)
201144 {
202− atomic_t *v = (atomic_t *)l;
145+ ATOMIC_LONG_PFX(_t) *v = (ATOMIC_LONG_PFX(_t) *)l;
203146
204− return atomic_inc_and_test(v);
147+ return ATOMIC_LONG_PFX(_inc_and_test)(v);
205148 }
206149
207150 static inline int atomic_long_add_negative(long i, atomic_long_t *l)
208151 {
209− atomic_t *v = (atomic_t *)l;
152+ ATOMIC_LONG_PFX(_t) *v = (ATOMIC_LONG_PFX(_t) *)l;
210153
211− return atomic_add_negative(i, v);
212−}
213−
214−static inline long atomic_long_add_return(long i, atomic_long_t *l)
215−{
216− atomic_t *v = (atomic_t *)l;
217−
218− return (long)atomic_add_return(i, v);
219−}
220−
221−static inline long atomic_long_sub_return(long i, atomic_long_t *l)
222−{
223− atomic_t *v = (atomic_t *)l;
224−
225− return (long)atomic_sub_return(i, v);
154+ return ATOMIC_LONG_PFX(_add_negative)(i, v);
226155 }
227156
228157 static inline long atomic_long_inc_return(atomic_long_t *l)
229158 {
230− atomic_t *v = (atomic_t *)l;
159+ ATOMIC_LONG_PFX(_t) *v = (ATOMIC_LONG_PFX(_t) *)l;
231160
232− return (long)atomic_inc_return(v);
161+ return (long)ATOMIC_LONG_PFX(_inc_return)(v);
233162 }
234163
235164 static inline long atomic_long_dec_return(atomic_long_t *l)
236165 {
237− atomic_t *v = (atomic_t *)l;
166+ ATOMIC_LONG_PFX(_t) *v = (ATOMIC_LONG_PFX(_t) *)l;
238167
239− return (long)atomic_dec_return(v);
168+ return (long)ATOMIC_LONG_PFX(_dec_return)(v);
240169 }
241170
242171 static inline long atomic_long_add_unless(atomic_long_t *l, long a, long u)
243172 {
244− atomic_t *v = (atomic_t *)l;
173+ ATOMIC_LONG_PFX(_t) *v = (ATOMIC_LONG_PFX(_t) *)l;
245174
246− return (long)atomic_add_unless(v, a, u);
175+ return (long)ATOMIC_LONG_PFX(_add_unless)(v, a, u);
247176 }
248177
249−#define atomic_long_inc_not_zero(l) atomic_inc_not_zero((atomic_t *)(l))
250−
251−#define atomic_long_cmpxchg(l, old, new) \
252− (atomic_cmpxchg((atomic_t *)(l), (old), (new)))
253−#define atomic_long_xchg(v, new) \
254− (atomic_xchg((atomic_t *)(v), (new)))
255−
256−#endif /* BITS_PER_LONG == 64 */
178+#define atomic_long_inc_not_zero(l) \
179+ ATOMIC_LONG_PFX(_inc_not_zero)((ATOMIC_LONG_PFX(_t) *)(l))
257180
258181 #endif /* _ASM_GENERIC_ATOMIC_LONG_H */
include/asm-generic/atomic.h+6−5
@@ -98,15 +98,16 @@ ATOMIC_OP_RETURN(add, +) · 97 unmodified lines
9898 ATOMIC_OP_RETURN(sub, -)
9999 #endif
100100
101−#ifndef atomic_clear_mask
101+#ifndef atomic_and
102102 ATOMIC_OP(and, &)
103−#define atomic_clear_mask(i, v) atomic_and(~(i), (v))
104103 #endif
105104
106−#ifndef atomic_set_mask
107−#define CONFIG_ARCH_HAS_ATOMIC_OR
105+#ifndef atomic_or
108106 ATOMIC_OP(or, |)
109−#define atomic_set_mask(i, v) atomic_or((i), (v))
107+#endif
108+
109+#ifndef atomic_xor
110+ATOMIC_OP(xor, ^)
110111 #endif
111112
112113 #undef ATOMIC_OP_RETURN
include/asm-generic/atomic64.h+4−0
@@ -32,6 +32,10 @@ extern long long atomic64_##op##_return(long long a, atomic64_t *v); · 31 unmodified lines
3232 ATOMIC64_OPS(add)
3333 ATOMIC64_OPS(sub)
3434
35+ATOMIC64_OP(and)
36+ATOMIC64_OP(or)
37+ATOMIC64_OP(xor)
38+
3539 #undef ATOMIC64_OPS
3640 #undef ATOMIC64_OP_RETURN
3741 #undef ATOMIC64_OP
include/asm-generic/barrier.h+2−2
@@ -108,12 +108,12 @@ · 107 unmodified lines
108108 do { \
109109 compiletime_assert_atomic_type(*p); \
110110 smp_mb(); \
111− ACCESS_ONCE(*p) = (v); \
111+ WRITE_ONCE(*p, v); \
112112 } while (0)
113113
114114 #define smp_load_acquire(p) \
115115 ({ \
116− typeof(*p) ___p1 = ACCESS_ONCE(*p); \
116+ typeof(*p) ___p1 = READ_ONCE(*p); \
117117 compiletime_assert_atomic_type(*p); \
118118 smp_mb(); \
119119 ___p1; \
include/asm-generic/qrwlock.h+35−43
@@ -36,39 +36,39 @@ · 35 unmodified lines
3636 /*
3737 * External function declarations
3838 */
39−extern void queue_read_lock_slowpath(struct qrwlock *lock);
40−extern void queue_write_lock_slowpath(struct qrwlock *lock);
39+extern void queued_read_lock_slowpath(struct qrwlock *lock, u32 cnts);
40+extern void queued_write_lock_slowpath(struct qrwlock *lock);
4141
4242 /**
43− * queue_read_can_lock- would read_trylock() succeed?
43+ * queued_read_can_lock- would read_trylock() succeed?
4444 * @lock: Pointer to queue rwlock structure
4545 */
46−static inline int queue_read_can_lock(struct qrwlock *lock)
46+static inline int queued_read_can_lock(struct qrwlock *lock)
4747 {
4848 return !(atomic_read(&lock->cnts) & _QW_WMASK);
4949 }
5050
5151 /**
52− * queue_write_can_lock- would write_trylock() succeed?
52+ * queued_write_can_lock- would write_trylock() succeed?
5353 * @lock: Pointer to queue rwlock structure
5454 */
55−static inline int queue_write_can_lock(struct qrwlock *lock)
55+static inline int queued_write_can_lock(struct qrwlock *lock)
5656 {
5757 return !atomic_read(&lock->cnts);
5858 }
5959
6060 /**
61− * queue_read_trylock - try to acquire read lock of a queue rwlock
61+ * queued_read_trylock - try to acquire read lock of a queue rwlock
6262 * @lock : Pointer to queue rwlock structure
6363 * Return: 1 if lock acquired, 0 if failed
6464 */
65−static inline int queue_read_trylock(struct qrwlock *lock)
65+static inline int queued_read_trylock(struct qrwlock *lock)
6666 {
6767 u32 cnts;
6868
6969 cnts = atomic_read(&lock->cnts);
7070 if (likely(!(cnts & _QW_WMASK))) {
71− cnts = (u32)atomic_add_return(_QR_BIAS, &lock->cnts);
71+ cnts = (u32)atomic_add_return_acquire(_QR_BIAS, &lock->cnts);
7272 if (likely(!(cnts & _QW_WMASK)))
7373 return 1;
7474 atomic_sub(_QR_BIAS, &lock->cnts);
@@ -77,11 +77,11 @@ static inline int queue_read_trylock(struct qrwlock *lock) · 2 unmodified lines
7777 }
7878
7979 /**
80− * queue_write_trylock - try to acquire write lock of a queue rwlock
80+ * queued_write_trylock - try to acquire write lock of a queue rwlock
8181 * @lock : Pointer to queue rwlock structure
8282 * Return: 1 if lock acquired, 0 if failed
8383 */
84−static inline int queue_write_trylock(struct qrwlock *lock)
84+static inline int queued_write_trylock(struct qrwlock *lock)
8585 {
8686 u32 cnts;
8787
@@ -89,78 +89,70 @@ static inline int queue_write_trylock(struct qrwlock *lock) · 1 unmodified line
8989 if (unlikely(cnts))
9090 return 0;
9191
92− return likely(atomic_cmpxchg(&lock->cnts,
93− cnts, cnts | _QW_LOCKED) == cnts);
92+ return likely(atomic_cmpxchg_acquire(&lock->cnts,
93+ cnts, cnts | _QW_LOCKED) == cnts);
9494 }
9595 /**
96− * queue_read_lock - acquire read lock of a queue rwlock
96+ * queued_read_lock - acquire read lock of a queue rwlock
9797 * @lock: Pointer to queue rwlock structure
9898 */
99−static inline void queue_read_lock(struct qrwlock *lock)
99+static inline void queued_read_lock(struct qrwlock *lock)
100100 {
101101 u32 cnts;
102102
103− cnts = atomic_add_return(_QR_BIAS, &lock->cnts);
103+ cnts = atomic_add_return_acquire(_QR_BIAS, &lock->cnts);
104104 if (likely(!(cnts & _QW_WMASK)))
105105 return;
106106
107107 /* The slowpath will decrement the reader count, if necessary. */
108− queue_read_lock_slowpath(lock);
108+ queued_read_lock_slowpath(lock, cnts);
109109 }
110110
111111 /**
112− * queue_write_lock - acquire write lock of a queue rwlock
112+ * queued_write_lock - acquire write lock of a queue rwlock
113113 * @lock : Pointer to queue rwlock structure
114114 */
115−static inline void queue_write_lock(struct qrwlock *lock)
115+static inline void queued_write_lock(struct qrwlock *lock)
116116 {
117117 /* Optimize for the unfair lock case where the fair flag is 0. */
118− if (atomic_cmpxchg(&lock->cnts, 0, _QW_LOCKED) == 0)
118+ if (atomic_cmpxchg_acquire(&lock->cnts, 0, _QW_LOCKED) == 0)
119119 return;
120120
121− queue_write_lock_slowpath(lock);
121+ queued_write_lock_slowpath(lock);
122122 }
123123
124124 /**
125− * queue_read_unlock - release read lock of a queue rwlock
125+ * queued_read_unlock - release read lock of a queue rwlock
126126 * @lock : Pointer to queue rwlock structure
127127 */
128−static inline void queue_read_unlock(struct qrwlock *lock)
128+static inline void queued_read_unlock(struct qrwlock *lock)
129129 {
130130 /*
131131 * Atomically decrement the reader count
132132 */
133− smp_mb__before_atomic();
134− atomic_sub(_QR_BIAS, &lock->cnts);
133+ (void)atomic_sub_return_release(_QR_BIAS, &lock->cnts);
135134 }
136135
137−#ifndef queue_write_unlock
138136 /**
139− * queue_write_unlock - release write lock of a queue rwlock
137+ * queued_write_unlock - release write lock of a queue rwlock
140138 * @lock : Pointer to queue rwlock structure
141139 */
142−static inline void queue_write_unlock(struct qrwlock *lock)
140+static inline void queued_write_unlock(struct qrwlock *lock)
143141 {
144− /*
145− * If the writer field is atomic, it can be cleared directly.
146− * Otherwise, an atomic subtraction will be used to clear it.
147− */
148− smp_mb__before_atomic();
149− atomic_sub(_QW_LOCKED, &lock->cnts);
142+ smp_store_release((u8 *)&lock->cnts, 0);
150143 }
151−#endif
152144
153145 /*
154146 * Remapping rwlock architecture specific functions to the corresponding
155147 * queue rwlock functions.
156148 */
157−#define arch_read_can_lock(l) queue_read_can_lock(l)
158−#define arch_write_can_lock(l) queue_write_can_lock(l)
159−#define arch_read_lock(l) queue_read_lock(l)
160−#define arch_write_lock(l) queue_write_lock(l)
161−#define arch_read_trylock(l) queue_read_trylock(l)
162−#define arch_write_trylock(l) queue_write_trylock(l)
163−#define arch_read_unlock(l) queue_read_unlock(l)
164−#define arch_write_unlock(l) queue_write_unlock(l)
149+#define arch_read_can_lock(l) queued_read_can_lock(l)
150+#define arch_write_can_lock(l) queued_write_can_lock(l)
151+#define arch_read_lock(l) queued_read_lock(l)
152+#define arch_write_lock(l) queued_write_lock(l)
153+#define arch_read_trylock(l) queued_read_trylock(l)
154+#define arch_write_trylock(l) queued_write_trylock(l)
155+#define arch_read_unlock(l) queued_read_unlock(l)
156+#define arch_write_unlock(l) queued_write_unlock(l)
165157
166158 #endif /* __ASM_GENERIC_QRWLOCK_H */
include/linux/atomic.h+348−13
@@ -2,6 +2,329 @@ · 1 unmodified line
22 #ifndef _LINUX_ATOMIC_H
33 #define _LINUX_ATOMIC_H
44 #include <asm/atomic.h>
5+#include <asm/barrier.h>
6+
7+/*
8+ * Relaxed variants of xchg, cmpxchg and some atomic operations.
9+ *
10+ * We support four variants:
11+ *
12+ * - Fully ordered: The default implementation, no suffix required.
13+ * - Acquire: Provides ACQUIRE semantics, _acquire suffix.
14+ * - Release: Provides RELEASE semantics, _release suffix.
15+ * - Relaxed: No ordering guarantees, _relaxed suffix.
16+ *
17+ * For compound atomics performing both a load and a store, ACQUIRE
18+ * semantics apply only to the load and RELEASE semantics only to the
19+ * store portion of the operation. Note that a failed cmpxchg_acquire
20+ * does -not- imply any memory ordering constraints.
21+ *
22+ * See Documentation/memory-barriers.txt for ACQUIRE/RELEASE definitions.
23+ */
24+
25+#ifndef atomic_read_acquire
26+#define atomic_read_acquire(v) smp_load_acquire(&(v)->counter)
27+#endif
28+
29+#ifndef atomic_set_release
30+#define atomic_set_release(v, i) smp_store_release(&(v)->counter, (i))
31+#endif
32+
33+/*
34+ * The idea here is to build acquire/release variants by adding explicit
35+ * barriers on top of the relaxed variant. In the case where the relaxed
36+ * variant is already fully ordered, no additional barriers are needed.
37+ */
38+#define __atomic_op_acquire(op, args...) \
39+({ \
40+ typeof(op##_relaxed(args)) __ret = op##_relaxed(args); \
41+ smp_mb__after_atomic(); \
42+ __ret; \
43+})
44+
45+#define __atomic_op_release(op, args...) \
46+({ \
47+ smp_mb__before_atomic(); \
48+ op##_relaxed(args); \
49+})
50+
51+#define __atomic_op_fence(op, args...) \
52+({ \
53+ typeof(op##_relaxed(args)) __ret; \
54+ smp_mb__before_atomic(); \
55+ __ret = op##_relaxed(args); \
56+ smp_mb__after_atomic(); \
57+ __ret; \
58+})
59+
60+/* atomic_add_return_relaxed */
61+#ifndef atomic_add_return_relaxed
62+#define atomic_add_return_relaxed atomic_add_return
63+#define atomic_add_return_acquire atomic_add_return
64+#define atomic_add_return_release atomic_add_return
65+
66+#else /* atomic_add_return_relaxed */
67+
68+#ifndef atomic_add_return_acquire
69+#define atomic_add_return_acquire(...) \
70+ __atomic_op_acquire(atomic_add_return, __VA_ARGS__)
71+#endif
72+
73+#ifndef atomic_add_return_release
74+#define atomic_add_return_release(...) \
75+ __atomic_op_release(atomic_add_return, __VA_ARGS__)
76+#endif
77+
78+#ifndef atomic_add_return
79+#define atomic_add_return(...) \
80+ __atomic_op_fence(atomic_add_return, __VA_ARGS__)
81+#endif
82+#endif /* atomic_add_return_relaxed */
83+
84+/* atomic_sub_return_relaxed */
85+#ifndef atomic_sub_return_relaxed
86+#define atomic_sub_return_relaxed atomic_sub_return
87+#define atomic_sub_return_acquire atomic_sub_return
88+#define atomic_sub_return_release atomic_sub_return
89+
90+#else /* atomic_sub_return_relaxed */
91+
92+#ifndef atomic_sub_return_acquire
93+#define atomic_sub_return_acquire(...) \
94+ __atomic_op_acquire(atomic_sub_return, __VA_ARGS__)
95+#endif
96+
97+#ifndef atomic_sub_return_release
98+#define atomic_sub_return_release(...) \
99+ __atomic_op_release(atomic_sub_return, __VA_ARGS__)
100+#endif
101+
102+#ifndef atomic_sub_return
103+#define atomic_sub_return(...) \
104+ __atomic_op_fence(atomic_sub_return, __VA_ARGS__)
105+#endif
106+#endif /* atomic_sub_return_relaxed */
107+
108+/* atomic_xchg_relaxed */
109+#ifndef atomic_xchg_relaxed
110+#define atomic_xchg_relaxed atomic_xchg
111+#define atomic_xchg_acquire atomic_xchg
112+#define atomic_xchg_release atomic_xchg
113+
114+#else /* atomic_xchg_relaxed */
115+
116+#ifndef atomic_xchg_acquire
117+#define atomic_xchg_acquire(...) \
118+ __atomic_op_acquire(atomic_xchg, __VA_ARGS__)
119+#endif
120+
121+#ifndef atomic_xchg_release
122+#define atomic_xchg_release(...) \
123+ __atomic_op_release(atomic_xchg, __VA_ARGS__)
124+#endif
125+
126+#ifndef atomic_xchg
127+#define atomic_xchg(...) \
128+ __atomic_op_fence(atomic_xchg, __VA_ARGS__)
129+#endif
130+#endif /* atomic_xchg_relaxed */
131+
132+/* atomic_cmpxchg_relaxed */
133+#ifndef atomic_cmpxchg_relaxed
134+#define atomic_cmpxchg_relaxed atomic_cmpxchg
135+#define atomic_cmpxchg_acquire atomic_cmpxchg
136+#define atomic_cmpxchg_release atomic_cmpxchg
137+
138+#else /* atomic_cmpxchg_relaxed */
139+
140+#ifndef atomic_cmpxchg_acquire
141+#define atomic_cmpxchg_acquire(...) \
142+ __atomic_op_acquire(atomic_cmpxchg, __VA_ARGS__)
143+#endif
144+
145+#ifndef atomic_cmpxchg_release
146+#define atomic_cmpxchg_release(...) \
147+ __atomic_op_release(atomic_cmpxchg, __VA_ARGS__)
148+#endif
149+
150+#ifndef atomic_cmpxchg
151+#define atomic_cmpxchg(...) \
152+ __atomic_op_fence(atomic_cmpxchg, __VA_ARGS__)
153+#endif
154+#endif /* atomic_cmpxchg_relaxed */
155+
156+#ifndef atomic64_read_acquire
157+#define atomic64_read_acquire(v) smp_load_acquire(&(v)->counter)
158+#endif
159+
160+#ifndef atomic64_set_release
161+#define atomic64_set_release(v, i) smp_store_release(&(v)->counter, (i))
162+#endif
163+
164+/* atomic64_add_return_relaxed */
165+#ifndef atomic64_add_return_relaxed
166+#define atomic64_add_return_relaxed atomic64_add_return
167+#define atomic64_add_return_acquire atomic64_add_return
168+#define atomic64_add_return_release atomic64_add_return
169+
170+#else /* atomic64_add_return_relaxed */
171+
172+#ifndef atomic64_add_return_acquire
173+#define atomic64_add_return_acquire(...) \
174+ __atomic_op_acquire(atomic64_add_return, __VA_ARGS__)
175+#endif
176+
177+#ifndef atomic64_add_return_release
178+#define atomic64_add_return_release(...) \
179+ __atomic_op_release(atomic64_add_return, __VA_ARGS__)
180+#endif
181+
182+#ifndef atomic64_add_return
183+#define atomic64_add_return(...) \
184+ __atomic_op_fence(atomic64_add_return, __VA_ARGS__)
185+#endif
186+#endif /* atomic64_add_return_relaxed */
187+
188+/* atomic64_sub_return_relaxed */
189+#ifndef atomic64_sub_return_relaxed
190+#define atomic64_sub_return_relaxed atomic64_sub_return
191+#define atomic64_sub_return_acquire atomic64_sub_return
192+#define atomic64_sub_return_release atomic64_sub_return
193+
194+#else /* atomic64_sub_return_relaxed */
195+
196+#ifndef atomic64_sub_return_acquire
197+#define atomic64_sub_return_acquire(...) \
198+ __atomic_op_acquire(atomic64_sub_return, __VA_ARGS__)
199+#endif
200+
201+#ifndef atomic64_sub_return_release
202+#define atomic64_sub_return_release(...) \
203+ __atomic_op_release(atomic64_sub_return, __VA_ARGS__)
204+#endif
205+
206+#ifndef atomic64_sub_return
207+#define atomic64_sub_return(...) \
208+ __atomic_op_fence(atomic64_sub_return, __VA_ARGS__)
209+#endif
210+#endif /* atomic64_sub_return_relaxed */
211+
212+/* atomic64_xchg_relaxed */
213+#ifndef atomic64_xchg_relaxed
214+#define atomic64_xchg_relaxed atomic64_xchg
215+#define atomic64_xchg_acquire atomic64_xchg
216+#define atomic64_xchg_release atomic64_xchg
217+
218+#else /* atomic64_xchg_relaxed */
219+
220+#ifndef atomic64_xchg_acquire
221+#define atomic64_xchg_acquire(...) \
222+ __atomic_op_acquire(atomic64_xchg, __VA_ARGS__)
223+#endif
224+
225+#ifndef atomic64_xchg_release
226+#define atomic64_xchg_release(...) \
227+ __atomic_op_release(atomic64_xchg, __VA_ARGS__)
228+#endif
229+
230+#ifndef atomic64_xchg
231+#define atomic64_xchg(...) \
232+ __atomic_op_fence(atomic64_xchg, __VA_ARGS__)
233+#endif
234+#endif /* atomic64_xchg_relaxed */
235+
236+/* atomic64_cmpxchg_relaxed */
237+#ifndef atomic64_cmpxchg_relaxed
238+#define atomic64_cmpxchg_relaxed atomic64_cmpxchg
239+#define atomic64_cmpxchg_acquire atomic64_cmpxchg
240+#define atomic64_cmpxchg_release atomic64_cmpxchg
241+
242+#else /* atomic64_cmpxchg_relaxed */
243+
244+#ifndef atomic64_cmpxchg_acquire
245+#define atomic64_cmpxchg_acquire(...) \
246+ __atomic_op_acquire(atomic64_cmpxchg, __VA_ARGS__)
247+#endif
248+
249+#ifndef atomic64_cmpxchg_release
250+#define atomic64_cmpxchg_release(...) \
251+ __atomic_op_release(atomic64_cmpxchg, __VA_ARGS__)
252+#endif
253+
254+#ifndef atomic64_cmpxchg
255+#define atomic64_cmpxchg(...) \
256+ __atomic_op_fence(atomic64_cmpxchg, __VA_ARGS__)
257+#endif
258+#endif /* atomic64_cmpxchg_relaxed */
259+
260+/* cmpxchg_relaxed */
261+#ifndef cmpxchg_relaxed
262+#define cmpxchg_relaxed cmpxchg
263+#define cmpxchg_acquire cmpxchg
264+#define cmpxchg_release cmpxchg
265+
266+#else /* cmpxchg_relaxed */
267+
268+#ifndef cmpxchg_acquire
269+#define cmpxchg_acquire(...) \
270+ __atomic_op_acquire(cmpxchg, __VA_ARGS__)
271+#endif
272+
273+#ifndef cmpxchg_release
274+#define cmpxchg_release(...) \
275+ __atomic_op_release(cmpxchg, __VA_ARGS__)
276+#endif
277+
278+#ifndef cmpxchg
279+#define cmpxchg(...) \
280+ __atomic_op_fence(cmpxchg, __VA_ARGS__)
281+#endif
282+#endif /* cmpxchg_relaxed */
283+
284+/* cmpxchg64_relaxed */
285+#ifndef cmpxchg64_relaxed
286+#define cmpxchg64_relaxed cmpxchg64
287+#define cmpxchg64_acquire cmpxchg64
288+#define cmpxchg64_release cmpxchg64
289+
290+#else /* cmpxchg64_relaxed */
291+
292+#ifndef cmpxchg64_acquire
293+#define cmpxchg64_acquire(...) \
294+ __atomic_op_acquire(cmpxchg64, __VA_ARGS__)
295+#endif
296+
297+#ifndef cmpxchg64_release
298+#define cmpxchg64_release(...) \
299+ __atomic_op_release(cmpxchg64, __VA_ARGS__)
300+#endif
301+
302+#ifndef cmpxchg64
303+#define cmpxchg64(...) \
304+ __atomic_op_fence(cmpxchg64, __VA_ARGS__)
305+#endif
306+#endif /* cmpxchg64_relaxed */
307+
308+/* xchg_relaxed */
309+#ifndef xchg_relaxed
310+#define xchg_relaxed xchg
311+#define xchg_acquire xchg
312+#define xchg_release xchg
313+
314+#else /* xchg_relaxed */
315+
316+#ifndef xchg_acquire
317+#define xchg_acquire(...) __atomic_op_acquire(xchg, __VA_ARGS__)
318+#endif
319+
320+#ifndef xchg_release
321+#define xchg_release(...) __atomic_op_release(xchg, __VA_ARGS__)
322+#endif
323+
324+#ifndef xchg
325+#define xchg(...) __atomic_op_fence(xchg, __VA_ARGS__)
326+#endif
327+#endif /* xchg_relaxed */
5328
6329 /**
7330 * atomic_add_unless - add unless the number is already a given value
@@ -28,6 +351,23 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u) · 20 unmodified lines
28351 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
29352 #endif
30353
354+#ifndef atomic_andnot
355+static inline void atomic_andnot(int i, atomic_t *v)
356+{
357+ atomic_and(~i, v);
358+}
359+#endif
360+
361+static inline __deprecated void atomic_clear_mask(unsigned int mask, atomic_t *v)
362+{
363+ atomic_andnot(mask, v);
364+}
365+
366+static inline __deprecated void atomic_set_mask(unsigned int mask, atomic_t *v)
367+{
368+ atomic_or(mask, v);
369+}
370+
31371 /**
32372 * atomic_inc_not_zero_hint - increment if not null
33373 * @v: pointer of type atomic_t
@@ -111,21 +451,16 @@ static inline int atomic_dec_if_positive(atomic_t *v) · 77 unmodified lines
111451 }
112452 #endif
113453
114−#ifndef CONFIG_ARCH_HAS_ATOMIC_OR
115−static inline void atomic_or(int i, atomic_t *v)
116−{
117− int old;
118− int new;
119−
120− do {
121− old = atomic_read(v);
122− new = old | i;
123− } while (atomic_cmpxchg(v, old, new) != old);
124−}
125−#endif /* #ifndef CONFIG_ARCH_HAS_ATOMIC_OR */
126−
127454 #include <asm-generic/atomic-long.h>
128455 #ifdef CONFIG_GENERIC_ATOMIC64
129456 #include <asm-generic/atomic64.h>
130457 #endif
458+
459+#ifndef atomic64_andnot
460+static inline void atomic64_andnot(long long i, atomic64_t *v)
461+{
462+ atomic64_and(~i, v);
463+}
464+#endif
465+
131466 #endif /* _LINUX_ATOMIC_H */
include/linux/compiler.h+6−1
@@ -252,7 +252,12 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s · 251 unmodified lines
252252 ({ union { typeof(x) __val; char __c[1]; } __u; __read_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
253253
254254 #define WRITE_ONCE(x, val) \
255− ({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
255+({ \
256+ union { typeof(x) __val; char __c[1]; } __u = \
257+ { .__val = (__force typeof(x)) (val) }; \
258+ __write_once_size(&(x), __u.__c, sizeof(x)); \
259+ __u.__val; \
260+})
256261
257262 /**
258263 * READ_ONCE_CTRL - Read a value heading a control dependency
include/linux/jump_label.h+210−51
@@ -7,17 +7,52 @@ · 6 unmodified lines
77 * Copyright (C) 2009-2012 Jason Baron <jbaron@redhat.com>
88 * Copyright (C) 2011-2012 Peter Zijlstra <pzijlstr@redhat.com>
99 *
10+ * DEPRECATED API:
11+ *
12+ * The use of 'struct static_key' directly, is now DEPRECATED. In addition
13+ * static_key_{true,false}() is also DEPRECATED. IE DO NOT use the following:
14+ *
15+ * struct static_key false = STATIC_KEY_INIT_FALSE;
16+ * struct static_key true = STATIC_KEY_INIT_TRUE;
17+ * static_key_true()
18+ * static_key_false()
19+ *
20+ * The updated API replacements are:
21+ *
22+ * DEFINE_STATIC_KEY_TRUE(key);
23+ * DEFINE_STATIC_KEY_FALSE(key);
24+ * static_key_likely()
25+ * statick_key_unlikely()
26+ *
1027 * Jump labels provide an interface to generate dynamic branches using
11− * self-modifying code. Assuming toolchain and architecture support, the result
12− * of a "if (static_key_false(&key))" statement is an unconditional branch (which
13− * defaults to false - and the true block is placed out of line).
28+ * self-modifying code. Assuming toolchain and architecture support, if we
29+ * define a "key" that is initially false via "DEFINE_STATIC_KEY_FALSE(key)",
30+ * an "if (static_branch_unlikely(&key))" statement is an unconditional branch
31+ * (which defaults to false - and the true block is placed out of line).
32+ * Similarly, we can define an initially true key via
33+ * "DEFINE_STATIC_KEY_TRUE(key)", and use it in the same
34+ * "if (static_branch_unlikely(&key))", in which case we will generate an
35+ * unconditional branch to the out-of-line true branch. Keys that are
36+ * initially true or false can be using in both static_branch_unlikely()
37+ * and static_branch_likely() statements.
38+ *
39+ * At runtime we can change the branch target by setting the key
40+ * to true via a call to static_branch_enable(), or false using
41+ * static_branch_disable(). If the direction of the branch is switched by
42+ * these calls then we run-time modify the branch target via a
43+ * no-op -> jump or jump -> no-op conversion. For example, for an
44+ * initially false key that is used in an "if (static_branch_unlikely(&key))"
45+ * statement, setting the key to true requires us to patch in a jump
46+ * to the out-of-line of true branch.
1447 *
15− * However at runtime we can change the branch target using
16− * static_key_slow_{inc,dec}(). These function as a 'reference' count on the key
17− * object, and for as long as there are references all branches referring to
18− * that particular key will point to the (out of line) true block.
48+ * In addtion to static_branch_{enable,disable}, we can also reference count
49+ * the key or branch direction via static_branch_{inc,dec}. Thus,
50+ * static_branch_inc() can be thought of as a 'make more true' and
51+ * static_branch_dec() as a 'make more false'. The inc()/dec()
52+ * interface is meant to be used exclusively from the inc()/dec() for a given
53+ * key.
1954 *
20− * Since this relies on modifying code, the static_key_slow_{inc,dec}() functions
55+ * Since this relies on modifying code, the branch modifying functions
2156 * must be considered absolute slow paths (machine wide synchronization etc.).
2257 * OTOH, since the affected branches are unconditional, their runtime overhead
2358 * will be absolutely minimal, esp. in the default (off) case where the total
@@ -29,20 +64,10 @@ · 5 unmodified lines
2964 * cause significant performance degradation. Struct static_key_deferred and
3065 * static_key_slow_dec_deferred() provide for this.
3166 *
32− * Lacking toolchain and or architecture support, jump labels fall back to a simple
33− * conditional branch.
34− *
35− * struct static_key my_key = STATIC_KEY_INIT_TRUE;
36− *
37− * if (static_key_true(&my_key)) {
38− * }
67+ * Lacking toolchain and or architecture support, static keys fall back to a
68+ * simple conditional branch.
3969 *
40− * will result in the true case being in-line and starts the key with a single
41− * reference. Mixing static_key_true() and static_key_false() on the same key is not
42− * allowed.
43− *
44− * Not initializing the key (static data is initialized to 0s anyway) is the
45− * same as using STATIC_KEY_INIT_FALSE.
70+ * Additional babbling in: Documentation/static-keys.txt
4671 */
4772
4873 #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
@@ -86,8 +111,8 @@ struct static_key { · 37 unmodified lines
86111 #ifndef __ASSEMBLY__
87112
88113 enum jump_label_type {
89− JUMP_LABEL_DISABLE = 0,
90− JUMP_LABEL_ENABLE,
114+ JUMP_LABEL_NOP = 0,
115+ JUMP_LABEL_JMP,
91116 };
92117
93118 struct module;
@@ -101,33 +126,18 @@ static inline int static_key_count(struct static_key *key) · 7 unmodified lines
101126
102127 #ifdef HAVE_JUMP_LABEL
103128
104−#define JUMP_LABEL_TYPE_FALSE_BRANCH 0UL
105−#define JUMP_LABEL_TYPE_TRUE_BRANCH 1UL
106−#define JUMP_LABEL_TYPE_MASK 1UL
107−
108−static
109−inline struct jump_entry *jump_label_get_entries(struct static_key *key)
110−{
111− return (struct jump_entry *)((unsigned long)key->entries
112− & ~JUMP_LABEL_TYPE_MASK);
113−}
114−
115−static inline bool jump_label_get_branch_default(struct static_key *key)
116−{
117− if (((unsigned long)key->entries & JUMP_LABEL_TYPE_MASK) ==
118− JUMP_LABEL_TYPE_TRUE_BRANCH)
119− return true;
120− return false;
121−}
129+#define JUMP_TYPE_FALSE 0UL
130+#define JUMP_TYPE_TRUE 1UL
131+#define JUMP_TYPE_MASK 1UL
122132
123133 static __always_inline bool static_key_false(struct static_key *key)
124134 {
125− return arch_static_branch(key);
135+ return arch_static_branch(key, false);
126136 }
127137
128138 static __always_inline bool static_key_true(struct static_key *key)
129139 {
130− return !static_key_false(key);
140+ return !arch_static_branch(key, true);
131141 }
132142
133143 extern struct jump_entry __start___jump_table[];
@@ -145,12 +155,12 @@ extern void static_key_slow_inc(struct static_key *key); · 11 unmodified lines
145155 extern void static_key_slow_dec(struct static_key *key);
146156 extern void jump_label_apply_nops(struct module *mod);
147157
148−#define STATIC_KEY_INIT_TRUE ((struct static_key) \
158+#define STATIC_KEY_INIT_TRUE \
149159 { .enabled = ATOMIC_INIT(1), \
150− .entries = (void *)JUMP_LABEL_TYPE_TRUE_BRANCH })
151−#define STATIC_KEY_INIT_FALSE ((struct static_key) \
160+ .entries = (void *)JUMP_TYPE_TRUE }
161+#define STATIC_KEY_INIT_FALSE \
152162 { .enabled = ATOMIC_INIT(0), \
153− .entries = (void *)JUMP_LABEL_TYPE_FALSE_BRANCH })
163+ .entries = (void *)JUMP_TYPE_FALSE }
154164
155165 #else /* !HAVE_JUMP_LABEL */
156166
@@ -198,10 +208,8 @@ static inline int jump_label_apply_nops(struct module *mod) · 41 unmodified lines
198208 return 0;
199209 }
200210
201−#define STATIC_KEY_INIT_TRUE ((struct static_key) \
202− { .enabled = ATOMIC_INIT(1) })
203−#define STATIC_KEY_INIT_FALSE ((struct static_key) \
204− { .enabled = ATOMIC_INIT(0) })
211+#define STATIC_KEY_INIT_TRUE { .enabled = ATOMIC_INIT(1) }
212+#define STATIC_KEY_INIT_FALSE { .enabled = ATOMIC_INIT(0) }
205213
206214 #endif /* HAVE_JUMP_LABEL */
207215
@@ -213,6 +221,157 @@ static inline bool static_key_enabled(struct static_key *key) · 5 unmodified lines
213221 return static_key_count(key) > 0;
214222 }
215223
224+static inline void static_key_enable(struct static_key *key)
225+{
226+ int count = static_key_count(key);
227+
228+ WARN_ON_ONCE(count < 0 || count > 1);
229+
230+ if (!count)
231+ static_key_slow_inc(key);
232+}
233+
234+static inline void static_key_disable(struct static_key *key)
235+{
236+ int count = static_key_count(key);
237+
238+ WARN_ON_ONCE(count < 0 || count > 1);
239+
240+ if (count)
241+ static_key_slow_dec(key);
242+}
243+
244+/* -------------------------------------------------------------------------- */
245+
246+/*
247+ * Two type wrappers around static_key, such that we can use compile time
248+ * type differentiation to emit the right code.
249+ *
250+ * All the below code is macros in order to play type games.
251+ */
252+
253+struct static_key_true {
254+ struct static_key key;
255+};
256+
257+struct static_key_false {
258+ struct static_key key;
259+};
260+
261+#define STATIC_KEY_TRUE_INIT (struct static_key_true) { .key = STATIC_KEY_INIT_TRUE, }
262+#define STATIC_KEY_FALSE_INIT (struct static_key_false){ .key = STATIC_KEY_INIT_FALSE, }
263+
264+#define DEFINE_STATIC_KEY_TRUE(name) \
265+ struct static_key_true name = STATIC_KEY_TRUE_INIT
266+
267+#define DEFINE_STATIC_KEY_FALSE(name) \
268+ struct static_key_false name = STATIC_KEY_FALSE_INIT
269+
270+#ifdef HAVE_JUMP_LABEL
271+
272+/*
273+ * Combine the right initial value (type) with the right branch order
274+ * to generate the desired result.
275+ *
276+ *
277+ * type\branch| likely (1) | unlikely (0)
278+ * -----------+-----------------------+------------------
279+ * | |
280+ * true (1) | ... | ...
281+ * | NOP | JMP L
282+ * | <br-stmts> | 1: ...
283+ * | L: ... |
284+ * | |
285+ * | | L: <br-stmts>
286+ * | | jmp 1b
287+ * | |
288+ * -----------+-----------------------+------------------
289+ * | |
290+ * false (0) | ... | ...
291+ * | JMP L | NOP
292+ * | <br-stmts> | 1: ...
293+ * | L: ... |
294+ * | |
295+ * | | L: <br-stmts>
296+ * | | jmp 1b
297+ * | |
298+ * -----------+-----------------------+------------------
299+ *
300+ * The initial value is encoded in the LSB of static_key::entries,
301+ * type: 0 = false, 1 = true.
302+ *
303+ * The branch type is encoded in the LSB of jump_entry::key,
304+ * branch: 0 = unlikely, 1 = likely.
305+ *
306+ * This gives the following logic table:
307+ *
308+ * enabled type branch instuction
309+ * -----------------------------+-----------
310+ * 0 0 0 | NOP
311+ * 0 0 1 | JMP
312+ * 0 1 0 | NOP
313+ * 0 1 1 | JMP
314+ *
315+ * 1 0 0 | JMP
316+ * 1 0 1 | NOP
317+ * 1 1 0 | JMP
318+ * 1 1 1 | NOP
319+ *
320+ * Which gives the following functions:
321+ *
322+ * dynamic: instruction = enabled ^ branch
323+ * static: instruction = type ^ branch
324+ *
325+ * See jump_label_type() / jump_label_init_type().
326+ */
327+
328+extern bool ____wrong_branch_error(void);
329+
330+#define static_branch_likely(x) \
331+({ \
332+ bool branch; \
333+ if (__builtin_types_compatible_p(typeof(*x), struct static_key_true)) \
334+ branch = !arch_static_branch(&(x)->key, true); \
335+ else if (__builtin_types_compatible_p(typeof(*x), struct static_key_false)) \
336+ branch = !arch_static_branch_jump(&(x)->key, true); \
337+ else \
338+ branch = ____wrong_branch_error(); \
339+ branch; \
340+})
341+
342+#define static_branch_unlikely(x) \
343+({ \
344+ bool branch; \
345+ if (__builtin_types_compatible_p(typeof(*x), struct static_key_true)) \
346+ branch = arch_static_branch_jump(&(x)->key, false); \
347+ else if (__builtin_types_compatible_p(typeof(*x), struct static_key_false)) \
348+ branch = arch_static_branch(&(x)->key, false); \
349+ else \
350+ branch = ____wrong_branch_error(); \
351+ branch; \
352+})
353+
354+#else /* !HAVE_JUMP_LABEL */
355+
356+#define static_branch_likely(x) likely(static_key_enabled(&(x)->key))
357+#define static_branch_unlikely(x) unlikely(static_key_enabled(&(x)->key))
358+
359+#endif /* HAVE_JUMP_LABEL */
360+
361+/*
362+ * Advanced usage; refcount, branch is enabled when: count != 0
363+ */
364+
365+#define static_branch_inc(x) static_key_slow_inc(&(x)->key)
366+#define static_branch_dec(x) static_key_slow_dec(&(x)->key)
367+
368+/*
369+ * Normal usage; boolean enable/disable.
370+ */
371+
372+#define static_branch_enable(x) static_key_enable(&(x)->key)
373+#define static_branch_disable(x) static_key_disable(&(x)->key)
374+
216375 #endif /* _LINUX_JUMP_LABEL_H */
217376
218377 #endif /* __ASSEMBLY__ */
include/linux/llist.h+1−1
@@ -55,8 +55,8 @@ · 54 unmodified lines
5555 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
5656 */
5757
58+#include <linux/atomic.h>
5859 #include <linux/kernel.h>
59−#include <asm/cmpxchg.h>
6060
6161 struct llist_head {
6262 struct llist_node *first;
kernel/futex.c+96−4
@@ -64,6 +64,7 @@ · 63 unmodified lines
6464 #include <linux/hugetlb.h>
6565 #include <linux/freezer.h>
6666 #include <linux/bootmem.h>
67+#include <linux/fault-inject.h>
6768
6869 #include <asm/futex.h>
6970
@@ -258,6 +259,66 @@ static unsigned long __read_mostly futex_hashsize; · 188 unmodified lines
258259
259260 static struct futex_hash_bucket *futex_queues;
260261
262+/*
263+ * Fault injections for futexes.
264+ */
265+#ifdef CONFIG_FAIL_FUTEX
266+
267+static struct {
268+ struct fault_attr attr;
269+
270+ u32 ignore_private;
271+} fail_futex = {
272+ .attr = FAULT_ATTR_INITIALIZER,
273+ .ignore_private = 0,
274+};
275+
276+static int __init setup_fail_futex(char *str)
277+{
278+ return setup_fault_attr(&fail_futex.attr, str);
279+}
280+__setup("fail_futex=", setup_fail_futex);
281+
282+static bool should_fail_futex(bool fshared)
283+{
284+ if (fail_futex.ignore_private && !fshared)
285+ return false;
286+
287+ return should_fail(&fail_futex.attr, 1);
288+}
289+
290+#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
291+
292+static int __init fail_futex_debugfs(void)
293+{
294+ umode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
295+ struct dentry *dir;
296+
297+ dir = fault_create_debugfs_attr("fail_futex", NULL,
298+ &fail_futex.attr);
299+ if (IS_ERR(dir))
300+ return PTR_ERR(dir);
301+
302+ if (!debugfs_create_bool("ignore-private", mode, dir,
303+ &fail_futex.ignore_private)) {
304+ debugfs_remove_recursive(dir);
305+ return -ENOMEM;
306+ }
307+
308+ return 0;
309+}
310+
311+late_initcall(fail_futex_debugfs);
312+
313+#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
314+
315+#else
316+static inline bool should_fail_futex(bool fshared)
317+{
318+ return false;
319+}
320+#endif /* CONFIG_FAIL_FUTEX */
321+
261322 static inline void futex_get_mm(union futex_key *key)
262323 {
263324 atomic_inc(&key->private.mm->mm_count);
@@ -413,6 +474,9 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw) · 149 unmodified lines
413474 if (unlikely(!access_ok(rw, uaddr, sizeof(u32))))
414475 return -EFAULT;
415476
477+ if (unlikely(should_fail_futex(fshared)))
478+ return -EFAULT;
479+
416480 /*
417481 * PROCESS_PRIVATE futexes are fast.
418482 * As the mm cannot disappear under us and the 'key' only needs
@@ -428,6 +492,10 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw) · 9 unmodified lines
428492 }
429493
430494 again:
495+ /* Ignore any VERIFY_READ mapping (futex common case) */
496+ if (unlikely(should_fail_futex(fshared)))
497+ return -EFAULT;
498+
431499 err = get_user_pages_fast(address, 1, 1, &page);
432500 /*
433501 * If write access is not required (eg. FUTEX_WAIT), try
@@ -516,7 +584,7 @@ again: · 82 unmodified lines
516584 * A RO anonymous page will never change and thus doesn't make
517585 * sense for futex operations.
518586 */
519− if (ro) {
587+ if (unlikely(should_fail_futex(fshared)) || ro) {
520588 err = -EFAULT;
521589 goto out;
522590 }
@@ -974,6 +1042,9 @@ static int lock_pi_update_atomic(u32 __user *uaddr, u32 uval, u32 newval) · 451 unmodified lines
9741042 {
9751043 u32 uninitialized_var(curval);
9761044
1045+ if (unlikely(should_fail_futex(true)))
1046+ return -EFAULT;
1047+
9771048 if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)))
9781049 return -EFAULT;
9791050
@@ -1015,12 +1086,18 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, · 35 unmodified lines
10151086 if (get_futex_value_locked(&uval, uaddr))
10161087 return -EFAULT;
10171088
1089+ if (unlikely(should_fail_futex(true)))
1090+ return -EFAULT;
1091+
10181092 /*
10191093 * Detect deadlocks.
10201094 */
10211095 if ((unlikely((uval & FUTEX_TID_MASK) == vpid)))
10221096 return -EDEADLK;
10231097
1098+ if ((unlikely(should_fail_futex(true))))
1099+ return -EDEADLK;
1100+
10241101 /*
10251102 * Lookup existing state first. If it exists, try to attach to
10261103 * its pi_state.
@@ -1155,6 +1232,9 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this, · 128 unmodified lines
11551232 */
11561233 newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
11571234
1235+ if (unlikely(should_fail_futex(true)))
1236+ ret = -EFAULT;
1237+
11581238 if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
11591239 ret = -EFAULT;
11601240 else if (curval != uval)
@@ -1457,6 +1537,9 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex, · 296 unmodified lines
14571537 if (get_futex_value_locked(&curval, pifutex))
14581538 return -EFAULT;
14591539
1540+ if (unlikely(should_fail_futex(true)))
1541+ return -EFAULT;
1542+
14601543 /*
14611544 * Find the top_waiter and determine if there are additional waiters.
14621545 * If the caller intends to requeue more than 1 waiter to pifutex,
@@ -2268,8 +2351,11 @@ static long futex_wait_restart(struct restart_block *restart) · 805 unmodified lines
22682351 /*
22692352 * Userspace tried a 0 -> TID atomic transition of the futex value
22702353 * and failed. The kernel side here does the whole locking operation:
2271− * if there are waiters then it will block, it does PI, etc. (Due to
2272− * races the kernel might see a 0 value of the futex too.)
2354+ * if there are waiters then it will block as a consequence of relying
2355+ * on rt-mutexes, it does PI, etc. (Due to races the kernel might see
2356+ * a 0 value of the futex too.).
2357+ *
2358+ * Also serves as futex trylock_pi()'ing, and due semantics.
22732359 */
22742360 static int futex_lock_pi(u32 __user *uaddr, unsigned int flags,
22752361 ktime_t *time, int trylock)
@@ -2300,6 +2386,10 @@ retry_private: · 24 unmodified lines
23002386
23012387 ret = futex_lock_pi_atomic(uaddr, hb, &q.key, &q.pi_state, current, 0);
23022388 if (unlikely(ret)) {
2389+ /*
2390+ * Atomic work succeeded and we got the lock,
2391+ * or failed. Either way, we do _not_ block.
2392+ */
23032393 switch (ret) {
23042394 case 1:
23052395 /* We got the lock. */
@@ -2530,7 +2620,7 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb, · 224 unmodified lines
25302620 * futex_wait_requeue_pi() - Wait on uaddr and take uaddr2
25312621 * @uaddr: the futex we initially wait on (non-pi)
25322622 * @flags: futex flags (FLAGS_SHARED, FLAGS_CLOCKRT, etc.), they must be
2533− * the same type, no requeueing from private to shared, etc.
2623+ * the same type, no requeueing from private to shared, etc.
25342624 * @val: the expected value of uaddr
25352625 * @abs_time: absolute timeout
25362626 * @bitset: 32 bit wakeup bitset set by userspace, defaults to all
@@ -3005,6 +3095,8 @@ SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val, · 468 unmodified lines
30053095 if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI ||
30063096 cmd == FUTEX_WAIT_BITSET ||
30073097 cmd == FUTEX_WAIT_REQUEUE_PI)) {
3098+ if (unlikely(should_fail_futex(!(op & FUTEX_PRIVATE_FLAG))))
3099+ return -EFAULT;
30083100 if (copy_from_user(&ts, utime, sizeof(ts)) != 0)
30093101 return -EFAULT;
30103102 if (!timespec_valid(&ts))
kernel/jump_label.c+109−49
@@ -54,7 +54,7 @@ jump_label_sort_entries(struct jump_entry *start, struct jump_entry *stop) · 53 unmodified lines
5454 sort(start, size, sizeof(struct jump_entry), jump_label_cmp, NULL);
5555 }
5656
57−static void jump_label_update(struct static_key *key, int enable);
57+static void jump_label_update(struct static_key *key);
5858
5959 void static_key_slow_inc(struct static_key *key)
6060 {
@@ -63,13 +63,8 @@ void static_key_slow_inc(struct static_key *key) · 2 unmodified lines
6363 return;
6464
6565 jump_label_lock();
66− if (atomic_read(&key->enabled) == 0) {
67− if (!jump_label_get_branch_default(key))
68− jump_label_update(key, JUMP_LABEL_ENABLE);
69− else
70− jump_label_update(key, JUMP_LABEL_DISABLE);
71− }
72− atomic_inc(&key->enabled);
66+ if (atomic_inc_return(&key->enabled) == 1)
67+ jump_label_update(key);
7368 jump_label_unlock();
7469 }
7570 EXPORT_SYMBOL_GPL(static_key_slow_inc);
@@ -87,10 +82,7 @@ static void __static_key_slow_dec(struct static_key *key, · 11 unmodified lines
8782 atomic_inc(&key->enabled);
8883 schedule_delayed_work(work, rate_limit);
8984 } else {
90− if (!jump_label_get_branch_default(key))
91− jump_label_update(key, JUMP_LABEL_DISABLE);
92− else
93− jump_label_update(key, JUMP_LABEL_ENABLE);
85+ jump_label_update(key);
9486 }
9587 jump_label_unlock();
9688 }
@@ -149,7 +141,7 @@ static int __jump_label_text_reserved(struct jump_entry *iter_start, · 52 unmodified lines
149141 return 0;
150142 }
151143
152−/*
144+/*
153145 * Update code which is definitely not currently executing.
154146 * Architectures which need heavyweight synchronization to modify
155147 * running code can override this to make the non-live update case
@@ -158,37 +150,54 @@ static int __jump_label_text_reserved(struct jump_entry *iter_start, · 2 unmodified lines
158150 void __weak __init_or_module arch_jump_label_transform_static(struct jump_entry *entry,
159151 enum jump_label_type type)
160152 {
161− arch_jump_label_transform(entry, type);
153+ arch_jump_label_transform(entry, type);
154+}
155+
156+static inline struct jump_entry *static_key_entries(struct static_key *key)
157+{
158+ return (struct jump_entry *)((unsigned long)key->entries & ~JUMP_TYPE_MASK);
159+}
160+
161+static inline bool static_key_type(struct static_key *key)
162+{
163+ return (unsigned long)key->entries & JUMP_TYPE_MASK;
164+}
165+
166+static inline struct static_key *jump_entry_key(struct jump_entry *entry)
167+{
168+ return (struct static_key *)((unsigned long)entry->key & ~1UL);
169+}
170+
171+static bool jump_entry_branch(struct jump_entry *entry)
172+{
173+ return (unsigned long)entry->key & 1UL;
174+}
175+
176+static enum jump_label_type jump_label_type(struct jump_entry *entry)
177+{
178+ struct static_key *key = jump_entry_key(entry);
179+ bool enabled = static_key_enabled(key);
180+ bool branch = jump_entry_branch(entry);
181+
182+ /* See the comment in linux/jump_label.h */
183+ return enabled ^ branch;
162184 }
163185
164186 static void __jump_label_update(struct static_key *key,
165187 struct jump_entry *entry,
166− struct jump_entry *stop, int enable)
188+ struct jump_entry *stop)
167189 {
168− for (; (entry < stop) &&
169− (entry->key == (jump_label_t)(unsigned long)key);
170− entry++) {
190+ for (; (entry < stop) && (jump_entry_key(entry) == key); entry++) {
171191 /*
172192 * entry->code set to 0 invalidates module init text sections
173193 * kernel_text_address() verifies we are not in core kernel
174194 * init code, see jump_label_invalidate_module_init().
175195 */
176196 if (entry->code && kernel_text_address(entry->code))
177− arch_jump_label_transform(entry, enable);
197+ arch_jump_label_transform(entry, jump_label_type(entry));
178198 }
179199 }
180200
181−static enum jump_label_type jump_label_type(struct static_key *key)
182−{
183− bool true_branch = jump_label_get_branch_default(key);
184− bool state = static_key_enabled(key);
185−
186− if ((!true_branch && state) || (true_branch && !state))
187− return JUMP_LABEL_ENABLE;
188−
189− return JUMP_LABEL_DISABLE;
190−}
191−
192201 void __init jump_label_init(void)
193202 {
194203 struct jump_entry *iter_start = __start___jump_table;
@@ -202,8 +211,11 @@ void __init jump_label_init(void) · 7 unmodified lines
202211 for (iter = iter_start; iter < iter_stop; iter++) {
203212 struct static_key *iterk;
204213
205− iterk = (struct static_key *)(unsigned long)iter->key;
206− arch_jump_label_transform_static(iter, jump_label_type(iterk));
214+ /* rewrite NOPs */
215+ if (jump_label_type(iter) == JUMP_LABEL_NOP)
216+ arch_jump_label_transform_static(iter, JUMP_LABEL_NOP);
217+
218+ iterk = jump_entry_key(iter);
207219 if (iterk == key)
208220 continue;
209221
@@ -222,6 +234,16 @@ void __init jump_label_init(void) · 12 unmodified lines
222234
223235 #ifdef CONFIG_MODULES
224236
237+static enum jump_label_type jump_label_init_type(struct jump_entry *entry)
238+{
239+ struct static_key *key = jump_entry_key(entry);
240+ bool type = static_key_type(key);
241+ bool branch = jump_entry_branch(entry);
242+
243+ /* See the comment in linux/jump_label.h */
244+ return type ^ branch;
245+}
246+
225247 struct static_key_mod {
226248 struct static_key_mod *next;
227249 struct jump_entry *entries;
@@ -243,17 +265,15 @@ static int __jump_label_mod_text_reserved(void *start, void *end) · 15 unmodified lines
243265 start, end);
244266 }
245267
246−static void __jump_label_mod_update(struct static_key *key, int enable)
268+static void __jump_label_mod_update(struct static_key *key)
247269 {
248− struct static_key_mod *mod = key->next;
270+ struct static_key_mod *mod;
249271
250− while (mod) {
272+ for (mod = key->next; mod; mod = mod->next) {
251273 struct module *m = mod->mod;
252274
253275 __jump_label_update(key, mod->entries,
254− m->jump_entries + m->num_jump_entries,
255− enable);
256− mod = mod->next;
276+ m->jump_entries + m->num_jump_entries);
257277 }
258278 }
259279
@@ -276,7 +296,9 @@ void jump_label_apply_nops(struct module *mod) · 16 unmodified lines
276296 return;
277297
278298 for (iter = iter_start; iter < iter_stop; iter++) {
279− arch_jump_label_transform_static(iter, JUMP_LABEL_DISABLE);
299+ /* Only write NOPs for arch_branch_static(). */
300+ if (jump_label_init_type(iter) == JUMP_LABEL_NOP)
301+ arch_jump_label_transform_static(iter, JUMP_LABEL_NOP);
280302 }
281303 }
282304
@@ -297,7 +319,7 @@ static int jump_label_add_module(struct module *mod) · 14 unmodified lines
297319 for (iter = iter_start; iter < iter_stop; iter++) {
298320 struct static_key *iterk;
299321
300− iterk = (struct static_key *)(unsigned long)iter->key;
322+ iterk = jump_entry_key(iter);
301323 if (iterk == key)
302324 continue;
303325
@@ -318,8 +340,9 @@ static int jump_label_add_module(struct module *mod) · 14 unmodified lines
318340 jlm->next = key->next;
319341 key->next = jlm;
320342
321− if (jump_label_type(key) == JUMP_LABEL_ENABLE)
322− __jump_label_update(key, iter, iter_stop, JUMP_LABEL_ENABLE);
343+ /* Only update if we've changed from our initial state */
344+ if (jump_label_type(iter) != jump_label_init_type(iter))
345+ __jump_label_update(key, iter, iter_stop);
323346 }
324347
325348 return 0;
@@ -334,10 +357,10 @@ static void jump_label_del_module(struct module *mod) · 8 unmodified lines
334357 struct static_key_mod *jlm, **prev;
335358
336359 for (iter = iter_start; iter < iter_stop; iter++) {
337− if (iter->key == (jump_label_t)(unsigned long)key)
360+ if (jump_entry_key(iter) == key)
338361 continue;
339362
340− key = (struct static_key *)(unsigned long)iter->key;
363+ key = jump_entry_key(iter);
341364
342365 if (within_module(iter->key, mod))
343366 continue;
@@ -439,14 +462,14 @@ int jump_label_text_reserved(void *start, void *end) · 95 unmodified lines
439462 return ret;
440463 }
441464
442−static void jump_label_update(struct static_key *key, int enable)
465+static void jump_label_update(struct static_key *key)
443466 {
444467 struct jump_entry *stop = __stop___jump_table;
445− struct jump_entry *entry = jump_label_get_entries(key);
468+ struct jump_entry *entry = static_key_entries(key);
446469 #ifdef CONFIG_MODULES
447470 struct module *mod;
448471
449− __jump_label_mod_update(key, enable);
472+ __jump_label_mod_update(key);
450473
451474 preempt_disable();
452475 mod = __module_address((unsigned long)key);
@@ -456,7 +479,44 @@ static void jump_label_update(struct static_key *key, int enable) · 3 unmodified lines
456479 #endif
457480 /* if there are no users, entry can be NULL */
458481 if (entry)
459− __jump_label_update(key, entry, stop, enable);
482+ __jump_label_update(key, entry, stop);
460483 }
461484
462−#endif
485+#ifdef CONFIG_STATIC_KEYS_SELFTEST
486+static DEFINE_STATIC_KEY_TRUE(sk_true);
487+static DEFINE_STATIC_KEY_FALSE(sk_false);
488+
489+static __init int jump_label_test(void)
490+{
491+ int i;
492+
493+ for (i = 0; i < 2; i++) {
494+ WARN_ON(static_key_enabled(&sk_true.key) != true);
495+ WARN_ON(static_key_enabled(&sk_false.key) != false);
496+
497+ WARN_ON(!static_branch_likely(&sk_true));
498+ WARN_ON(!static_branch_unlikely(&sk_true));
499+ WARN_ON(static_branch_likely(&sk_false));
500+ WARN_ON(static_branch_unlikely(&sk_false));
501+
502+ static_branch_disable(&sk_true);
503+ static_branch_enable(&sk_false);
504+
505+ WARN_ON(static_key_enabled(&sk_true.key) == true);
506+ WARN_ON(static_key_enabled(&sk_false.key) == false);
507+
508+ WARN_ON(static_branch_likely(&sk_true));
509+ WARN_ON(static_branch_unlikely(&sk_true));
510+ WARN_ON(!static_branch_likely(&sk_false));
511+ WARN_ON(!static_branch_unlikely(&sk_false));
512+
513+ static_branch_enable(&sk_true);
514+ static_branch_disable(&sk_false);
515+ }
516+
517+ return 0;
518+}
519+late_initcall(jump_label_test);
520+#endif /* STATIC_KEYS_SELFTEST */
521+
522+#endif /* HAVE_JUMP_LABEL */
kernel/locking/Makefile+0−1
@@ -20,7 +20,6 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o · 19 unmodified lines
2020 obj-$(CONFIG_QUEUED_SPINLOCKS) += qspinlock.o
2121 obj-$(CONFIG_RT_MUTEXES) += rtmutex.o
2222 obj-$(CONFIG_DEBUG_RT_MUTEXES) += rtmutex-debug.o
23−obj-$(CONFIG_RT_MUTEX_TESTER) += rtmutex-tester.o
2423 obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o
2524 obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
2625 obj-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
kernel/locking/qrwlock.c+22−25
@@ -55,27 +55,29 @@ rspin_until_writer_unlock(struct qrwlock *lock, u32 cnts) · 54 unmodified lines
5555 {
5656 while ((cnts & _QW_WMASK) == _QW_LOCKED) {
5757 cpu_relax_lowlatency();
58− cnts = smp_load_acquire((u32 *)&lock->cnts);
58+ cnts = atomic_read_acquire(&lock->cnts);
5959 }
6060 }
6161
6262 /**
63− * queue_read_lock_slowpath - acquire read lock of a queue rwlock
63+ * queued_read_lock_slowpath - acquire read lock of a queue rwlock
6464 * @lock: Pointer to queue rwlock structure
65+ * @cnts: Current qrwlock lock value
6566 */
66−void queue_read_lock_slowpath(struct qrwlock *lock)
67+void queued_read_lock_slowpath(struct qrwlock *lock, u32 cnts)
6768 {
68− u32 cnts;
69−
7069 /*
7170 * Readers come here when they cannot get the lock without waiting
7271 */
7372 if (unlikely(in_interrupt())) {
7473 /*
75− * Readers in interrupt context will spin until the lock is
76− * available without waiting in the queue.
74+ * Readers in interrupt context will get the lock immediately
75+ * if the writer is just waiting (not holding the lock yet).
76+ * The rspin_until_writer_unlock() function returns immediately
77+ * in this case. Otherwise, they will spin (with ACQUIRE
78+ * semantics) until the lock is available without waiting in
79+ * the queue.
7780 */
78− cnts = smp_load_acquire((u32 *)&lock->cnts);
7981 rspin_until_writer_unlock(lock, cnts);
8082 return;
8183 }
@@ -87,16 +89,11 @@ void queue_read_lock_slowpath(struct qrwlock *lock) · 5 unmodified lines
8789 arch_spin_lock(&lock->lock);
8890
8991 /*
90− * At the head of the wait queue now, wait until the writer state
91− * goes to 0 and then try to increment the reader count and get
92− * the lock. It is possible that an incoming writer may steal the
93− * lock in the interim, so it is necessary to check the writer byte
94− * to make sure that the write lock isn't taken.
92+ * The ACQUIRE semantics of the following spinning code ensure
93+ * that accesses can't leak upwards out of our subsequent critical
94+ * section in the case that the lock is currently held for write.
9595 */
96− while (atomic_read(&lock->cnts) & _QW_WMASK)
97− cpu_relax_lowlatency();
98−
99− cnts = atomic_add_return(_QR_BIAS, &lock->cnts) - _QR_BIAS;
96+ cnts = atomic_add_return_acquire(_QR_BIAS, &lock->cnts) - _QR_BIAS;
10097 rspin_until_writer_unlock(lock, cnts);
10198
10299 /*
@@ -104,13 +101,13 @@ void queue_read_lock_slowpath(struct qrwlock *lock) · 1 unmodified line
104101 */
105102 arch_spin_unlock(&lock->lock);
106103 }
107−EXPORT_SYMBOL(queue_read_lock_slowpath);
104+EXPORT_SYMBOL(queued_read_lock_slowpath);
108105
109106 /**
110− * queue_write_lock_slowpath - acquire write lock of a queue rwlock
107+ * queued_write_lock_slowpath - acquire write lock of a queue rwlock
111108 * @lock : Pointer to queue rwlock structure
112109 */
113−void queue_write_lock_slowpath(struct qrwlock *lock)
110+void queued_write_lock_slowpath(struct qrwlock *lock)
114111 {
115112 u32 cnts;
116113
@@ -119,7 +116,7 @@ void queue_write_lock_slowpath(struct qrwlock *lock) · 2 unmodified lines
119116
120117 /* Try to acquire the lock directly if no reader is present */
121118 if (!atomic_read(&lock->cnts) &&
122− (atomic_cmpxchg(&lock->cnts, 0, _QW_LOCKED) == 0))
119+ (atomic_cmpxchg_acquire(&lock->cnts, 0, _QW_LOCKED) == 0))
123120 goto unlock;
124121
125122 /*
@@ -130,7 +127,7 @@ void queue_write_lock_slowpath(struct qrwlock *lock) · 4 unmodified lines
130127 struct __qrwlock *l = (struct __qrwlock *)lock;
131128
132129 if (!READ_ONCE(l->wmode) &&
133− (cmpxchg(&l->wmode, 0, _QW_WAITING) == 0))
130+ (cmpxchg_relaxed(&l->wmode, 0, _QW_WAITING) == 0))
134131 break;
135132
136133 cpu_relax_lowlatency();
@@ -140,8 +137,8 @@ void queue_write_lock_slowpath(struct qrwlock *lock) · 3 unmodified lines
140137 for (;;) {
141138 cnts = atomic_read(&lock->cnts);
142139 if ((cnts == _QW_WAITING) &&
143− (atomic_cmpxchg(&lock->cnts, _QW_WAITING,
144− _QW_LOCKED) == _QW_WAITING))
140+ (atomic_cmpxchg_acquire(&lock->cnts, _QW_WAITING,
141+ _QW_LOCKED) == _QW_WAITING))
145142 break;
146143
147144 cpu_relax_lowlatency();
@@ -149,4 +146,4 @@ void queue_write_lock_slowpath(struct qrwlock *lock) · 1 unmodified line
149146 unlock:
150147 arch_spin_unlock(&lock->lock);
151148 }
152−EXPORT_SYMBOL(queue_write_lock_slowpath);
149+EXPORT_SYMBOL(queued_write_lock_slowpath);
kernel/locking/qspinlock.c+3−3
@@ -239,8 +239,8 @@ static __always_inline void set_locked(struct qspinlock *lock) · 238 unmodified lines
239239
240240 static __always_inline void __pv_init_node(struct mcs_spinlock *node) { }
241241 static __always_inline void __pv_wait_node(struct mcs_spinlock *node) { }
242−static __always_inline void __pv_kick_node(struct mcs_spinlock *node) { }
243−
242+static __always_inline void __pv_kick_node(struct qspinlock *lock,
243+ struct mcs_spinlock *node) { }
244244 static __always_inline void __pv_wait_head(struct qspinlock *lock,
245245 struct mcs_spinlock *node) { }
246246
@@ -440,7 +440,7 @@ queue: · 193 unmodified lines
440440 cpu_relax();
441441
442442 arch_mcs_spin_unlock_contended(&next->locked);
443− pv_kick_node(next);
443+ pv_kick_node(lock, next);
444444
445445 release:
446446 /*
kernel/locking/qspinlock_paravirt.h+73−29
@@ -22,9 +22,14 @@ · 21 unmodified lines
2222
2323 #define _Q_SLOW_VAL (3U << _Q_LOCKED_OFFSET)
2424
25+/*
26+ * Queue node uses: vcpu_running & vcpu_halted.
27+ * Queue head uses: vcpu_running & vcpu_hashed.
28+ */
2529 enum vcpu_state {
2630 vcpu_running = 0,
27− vcpu_halted,
31+ vcpu_halted, /* Used only in pv_wait_node */
32+ vcpu_hashed, /* = pv_hash'ed + vcpu_halted */
2833 };
2934
3035 struct pv_node {
@@ -153,7 +158,8 @@ static void pv_init_node(struct mcs_spinlock *node) · 122 unmodified lines
153158
154159 /*
155160 * Wait for node->locked to become true, halt the vcpu after a short spin.
156− * pv_kick_node() is used to wake the vcpu again.
161+ * pv_kick_node() is used to set _Q_SLOW_VAL and fill in hash table on its
162+ * behalf.
157163 */
158164 static void pv_wait_node(struct mcs_spinlock *node)
159165 {
@@ -172,9 +178,9 @@ static void pv_wait_node(struct mcs_spinlock *node) · 12 unmodified lines
172178 *
173179 * [S] pn->state = vcpu_halted [S] next->locked = 1
174180 * MB MB
175− * [L] pn->locked [RmW] pn->state = vcpu_running
181+ * [L] pn->locked [RmW] pn->state = vcpu_hashed
176182 *
177− * Matches the xchg() from pv_kick_node().
183+ * Matches the cmpxchg() from pv_kick_node().
178184 */
179185 smp_store_mb(pn->state, vcpu_halted);
180186
@@ -182,9 +188,10 @@ static void pv_wait_node(struct mcs_spinlock *node) · 1 unmodified line
182188 pv_wait(&pn->state, vcpu_halted);
183189
184190 /*
185− * Reset the vCPU state to avoid unncessary CPU kicking
191+ * If pv_kick_node() changed us to vcpu_hashed, retain that value
192+ * so that pv_wait_head() knows to not also try to hash this lock.
186193 */
187− WRITE_ONCE(pn->state, vcpu_running);
194+ cmpxchg(&pn->state, vcpu_halted, vcpu_running);
188195
189196 /*
190197 * If the locked flag is still not set after wakeup, it is a
@@ -194,6 +201,7 @@ static void pv_wait_node(struct mcs_spinlock *node) · 3 unmodified lines
194201 * MCS lock will be released soon.
195202 */
196203 }
204+
197205 /*
198206 * By now our node->locked should be 1 and our caller will not actually
199207 * spin-wait for it. We do however rely on our caller to do a
@@ -202,24 +210,35 @@ static void pv_wait_node(struct mcs_spinlock *node) · 2 unmodified lines
202210 }
203211
204212 /*
205− * Called after setting next->locked = 1, used to wake those stuck in
206− * pv_wait_node().
213+ * Called after setting next->locked = 1 when we're the lock owner.
214+ *
215+ * Instead of waking the waiters stuck in pv_wait_node() advance their state such
216+ * that they're waiting in pv_wait_head(), this avoids a wake/sleep cycle.
207217 */
208−static void pv_kick_node(struct mcs_spinlock *node)
218+static void pv_kick_node(struct qspinlock *lock, struct mcs_spinlock *node)
209219 {
210220 struct pv_node *pn = (struct pv_node *)node;
221+ struct __qspinlock *l = (void *)lock;
211222
212223 /*
213− * Note that because node->locked is already set, this actual
214− * mcs_spinlock entry could be re-used already.
224+ * If the vCPU is indeed halted, advance its state to match that of
225+ * pv_wait_node(). If OTOH this fails, the vCPU was running and will
226+ * observe its next->locked value and advance itself.
215227 *
216− * This should be fine however, kicking people for no reason is
217− * harmless.
228+ * Matches with smp_store_mb() and cmpxchg() in pv_wait_node()
229+ */
230+ if (cmpxchg(&pn->state, vcpu_halted, vcpu_hashed) != vcpu_halted)
231+ return;
232+
233+ /*
234+ * Put the lock into the hash table and set the _Q_SLOW_VAL.
218235 *
219− * See the comment in pv_wait_node().
236+ * As this is the same vCPU that will check the _Q_SLOW_VAL value and
237+ * the hash table later on at unlock time, no atomic instruction is
238+ * needed.
220239 */
221− if (xchg(&pn->state, vcpu_running) == vcpu_halted)
222− pv_kick(pn->cpu);
240+ WRITE_ONCE(l->locked, _Q_SLOW_VAL);
241+ (void)pv_hash(lock, pn);
223242 }
224243
225244 /*
@@ -233,6 +252,13 @@ static void pv_wait_head(struct qspinlock *lock, struct mcs_spinlock *node) · 7 unmodified lines
233252 struct qspinlock **lp = NULL;
234253 int loop;
235254
255+ /*
256+ * If pv_kick_node() already advanced our state, we don't need to
257+ * insert ourselves into the hash table anymore.
258+ */
259+ if (READ_ONCE(pn->state) == vcpu_hashed)
260+ lp = (struct qspinlock **)1;
261+
236262 for (;;) {
237263 for (loop = SPIN_THRESHOLD; loop; loop--) {
238264 if (!READ_ONCE(l->locked))
@@ -240,17 +266,22 @@ static void pv_wait_head(struct qspinlock *lock, struct mcs_spinlock *node) · 1 unmodified line
240266 cpu_relax();
241267 }
242268
243− WRITE_ONCE(pn->state, vcpu_halted);
244269 if (!lp) { /* ONCE */
270+ WRITE_ONCE(pn->state, vcpu_hashed);
245271 lp = pv_hash(lock, pn);
272+
246273 /*
247− * lp must be set before setting _Q_SLOW_VAL
274+ * We must hash before setting _Q_SLOW_VAL, such that
275+ * when we observe _Q_SLOW_VAL in __pv_queued_spin_unlock()
276+ * we'll be sure to be able to observe our hash entry.
248277 *
249− * [S] lp = lock [RmW] l = l->locked = 0
250− * MB MB
251− * [S] l->locked = _Q_SLOW_VAL [L] lp
278+ * [S] pn->state
279+ * [S] <hash> [Rmw] l->locked == _Q_SLOW_VAL
280+ * MB RMB
281+ * [RmW] l->locked = _Q_SLOW_VAL [L] <unhash>
282+ * [L] pn->state
252283 *
253− * Matches the cmpxchg() in __pv_queued_spin_unlock().
284+ * Matches the smp_rmb() in __pv_queued_spin_unlock().
254285 */
255286 if (!cmpxchg(&l->locked, _Q_LOCKED_VAL, _Q_SLOW_VAL)) {
256287 /*
@@ -287,23 +318,33 @@ __visible void __pv_queued_spin_unlock(struct qspinlock *lock) · 30 unmodified lines
287318 {
288319 struct __qspinlock *l = (void *)lock;
289320 struct pv_node *node;
290− u8 lockval = cmpxchg(&l->locked, _Q_LOCKED_VAL, 0);
321+ u8 locked;
291322
292323 /*
293324 * We must not unlock if SLOW, because in that case we must first
294325 * unhash. Otherwise it would be possible to have multiple @lock
295326 * entries, which would be BAD.
296327 */
297− if (likely(lockval == _Q_LOCKED_VAL))
328+ locked = cmpxchg(&l->locked, _Q_LOCKED_VAL, 0);
329+ if (likely(locked == _Q_LOCKED_VAL))
298330 return;
299331
300− if (unlikely(lockval != _Q_SLOW_VAL)) {
301− if (debug_locks_silent)
302− return;
303− WARN(1, "pvqspinlock: lock %p has corrupted value 0x%x!\n", lock, atomic_read(&lock->val));
332+ if (unlikely(locked != _Q_SLOW_VAL)) {
333+ WARN(!debug_locks_silent,
334+ "pvqspinlock: lock 0x%lx has corrupted value 0x%x!\n",
335+ (unsigned long)lock, atomic_read(&lock->val));
304336 return;
305337 }
306338
339+ /*
340+ * A failed cmpxchg doesn't provide any memory-ordering guarantees,
341+ * so we need a barrier to order the read of the node data in
342+ * pv_unhash *after* we've read the lock being _Q_SLOW_VAL.
343+ *
344+ * Matches the cmpxchg() in pv_wait_head() setting _Q_SLOW_VAL.
345+ */
346+ smp_rmb();
347+
307348 /*
308349 * Since the above failed to release, this must be the SLOW path.
309350 * Therefore start by looking up the blocked node and unhashing it.
@@ -319,8 +360,11 @@ __visible void __pv_queued_spin_unlock(struct qspinlock *lock) · 9 unmodified lines
319360 /*
320361 * At this point the memory pointed at by lock can be freed/reused,
321362 * however we can still use the pv_node to kick the CPU.
363+ * The other vCPU may not really be halted, but kicking an active
364+ * vCPU is harmless other than the additional latency in completing
365+ * the unlock.
322366 */
323− if (READ_ONCE(node->state) == vcpu_halted)
367+ if (READ_ONCE(node->state) == vcpu_hashed)
324368 pv_kick(node->cpu);
325369 }
326370 /*
kernel/locking/rtmutex-tester.c+0−420
@@ -1,420 +0,0 @@
1−/*
2− * RT-Mutex-tester: scriptable tester for rt mutexes
3− *
4− * started by Thomas Gleixner:
5− *
6− * Copyright (C) 2006, Timesys Corp., Thomas Gleixner <tglx@timesys.com>
7− *
8− */
9−#include <linux/device.h>
10−#include <linux/kthread.h>
11−#include <linux/export.h>
12−#include <linux/sched.h>
13−#include <linux/sched/rt.h>
14−#include <linux/spinlock.h>
15−#include <linux/timer.h>
16−#include <linux/freezer.h>
17−#include <linux/stat.h>
18−
19−#include "rtmutex.h"
20−
21−#define MAX_RT_TEST_THREADS 8
22−#define MAX_RT_TEST_MUTEXES 8
23−
24−static spinlock_t rttest_lock;
25−static atomic_t rttest_event;
26−
27−struct test_thread_data {
28− int opcode;
29− int opdata;
30− int mutexes[MAX_RT_TEST_MUTEXES];
31− int event;
32− struct device dev;
33−};
34−
35−static struct test_thread_data thread_data[MAX_RT_TEST_THREADS];
36−static struct task_struct *threads[MAX_RT_TEST_THREADS];
37−static struct rt_mutex mutexes[MAX_RT_TEST_MUTEXES];
38−
39−enum test_opcodes {
40− RTTEST_NOP = 0,
41− RTTEST_SCHEDOT, /* 1 Sched other, data = nice */
42− RTTEST_SCHEDRT, /* 2 Sched fifo, data = prio */
43− RTTEST_LOCK, /* 3 Lock uninterruptible, data = lockindex */
44− RTTEST_LOCKNOWAIT, /* 4 Lock uninterruptible no wait in wakeup, data = lockindex */
45− RTTEST_LOCKINT, /* 5 Lock interruptible, data = lockindex */
46− RTTEST_LOCKINTNOWAIT, /* 6 Lock interruptible no wait in wakeup, data = lockindex */
47− RTTEST_LOCKCONT, /* 7 Continue locking after the wakeup delay */
48− RTTEST_UNLOCK, /* 8 Unlock, data = lockindex */
49− /* 9, 10 - reserved for BKL commemoration */
50− RTTEST_SIGNAL = 11, /* 11 Signal other test thread, data = thread id */
51− RTTEST_RESETEVENT = 98, /* 98 Reset event counter */
52− RTTEST_RESET = 99, /* 99 Reset all pending operations */
53−};
54−
55−static int handle_op(struct test_thread_data *td, int lockwakeup)
56−{
57− int i, id, ret = -EINVAL;
58−
59− switch(td->opcode) {
60−
61− case RTTEST_NOP:
62− return 0;
63−
64− case RTTEST_LOCKCONT:
65− td->mutexes[td->opdata] = 1;
66− td->event = atomic_add_return(1, &rttest_event);
67− return 0;
68−
69− case RTTEST_RESET:
70− for (i = 0; i < MAX_RT_TEST_MUTEXES; i++) {
71− if (td->mutexes[i] == 4) {
72− rt_mutex_unlock(&mutexes[i]);
73− td->mutexes[i] = 0;
74− }
75− }
76− return 0;
77−
78− case RTTEST_RESETEVENT:
79− atomic_set(&rttest_event, 0);
80− return 0;
81−
82− default:
83− if (lockwakeup)
84− return ret;
85− }
86−
87− switch(td->opcode) {
88−
89− case RTTEST_LOCK:
90− case RTTEST_LOCKNOWAIT:
91− id = td->opdata;
92− if (id < 0 || id >= MAX_RT_TEST_MUTEXES)
93− return ret;
94−
95− td->mutexes[id] = 1;
96− td->event = atomic_add_return(1, &rttest_event);
97− rt_mutex_lock(&mutexes[id]);
98− td->event = atomic_add_return(1, &rttest_event);
99− td->mutexes[id] = 4;
100− return 0;
101−
102− case RTTEST_LOCKINT:
103− case RTTEST_LOCKINTNOWAIT:
104− id = td->opdata;
105− if (id < 0 || id >= MAX_RT_TEST_MUTEXES)
106− return ret;
107−
108− td->mutexes[id] = 1;
109− td->event = atomic_add_return(1, &rttest_event);
110− ret = rt_mutex_lock_interruptible(&mutexes[id], 0);
111− td->event = atomic_add_return(1, &rttest_event);
112− td->mutexes[id] = ret ? 0 : 4;
113− return ret ? -EINTR : 0;
114−
115− case RTTEST_UNLOCK:
116− id = td->opdata;
117− if (id < 0 || id >= MAX_RT_TEST_MUTEXES || td->mutexes[id] != 4)
118− return ret;
119−
120− td->event = atomic_add_return(1, &rttest_event);
121− rt_mutex_unlock(&mutexes[id]);
122− td->event = atomic_add_return(1, &rttest_event);
123− td->mutexes[id] = 0;
124− return 0;
125−
126− default:
127− break;
128− }
129− return ret;
130−}
131−
132−/*
133− * Schedule replacement for rtsem_down(). Only called for threads with
134− * PF_MUTEX_TESTER set.
135− *
136− * This allows us to have finegrained control over the event flow.
137− *
138− */
139−void schedule_rt_mutex_test(struct rt_mutex *mutex)
140−{
141− int tid, op, dat;
142− struct test_thread_data *td;
143−
144− /* We have to lookup the task */
145− for (tid = 0; tid < MAX_RT_TEST_THREADS; tid++) {
146− if (threads[tid] == current)
147− break;
148− }
149−
150− BUG_ON(tid == MAX_RT_TEST_THREADS);
151−
152− td = &thread_data[tid];
153−
154− op = td->opcode;
155− dat = td->opdata;
156−
157− switch (op) {
158− case RTTEST_LOCK:
159− case RTTEST_LOCKINT:
160− case RTTEST_LOCKNOWAIT:
161− case RTTEST_LOCKINTNOWAIT:
162− if (mutex != &mutexes[dat])
163− break;
164−
165− if (td->mutexes[dat] != 1)
166− break;
167−
168− td->mutexes[dat] = 2;
169− td->event = atomic_add_return(1, &rttest_event);
170− break;
171−
172− default:
173− break;
174− }
175−
176− schedule();
177−
178−
179− switch (op) {
180− case RTTEST_LOCK:
181− case RTTEST_LOCKINT:
182− if (mutex != &mutexes[dat])
183− return;
184−
185− if (td->mutexes[dat] != 2)
186− return;
187−
188− td->mutexes[dat] = 3;
189− td->event = atomic_add_return(1, &rttest_event);
190− break;
191−
192− case RTTEST_LOCKNOWAIT:
193− case RTTEST_LOCKINTNOWAIT:
194− if (mutex != &mutexes[dat])
195− return;
196−
197− if (td->mutexes[dat] != 2)
198− return;
199−
200− td->mutexes[dat] = 1;
201− td->event = atomic_add_return(1, &rttest_event);
202− return;
203−
204− default:
205− return;
206− }
207−
208− td->opcode = 0;
209−
210− for (;;) {
211− set_current_state(TASK_INTERRUPTIBLE);
212−
213− if (td->opcode > 0) {
214− int ret;
215−
216− set_current_state(TASK_RUNNING);
217− ret = handle_op(td, 1);
218− set_current_state(TASK_INTERRUPTIBLE);
219− if (td->opcode == RTTEST_LOCKCONT)
220− break;
221− td->opcode = ret;
222− }
223−
224− /* Wait for the next command to be executed */
225− schedule();
226− }
227−
228− /* Restore previous command and data */
229− td->opcode = op;
230− td->opdata = dat;
231−}
232−
233−static int test_func(void *data)
234−{
235− struct test_thread_data *td = data;
236− int ret;
237−
238− current->flags |= PF_MUTEX_TESTER;
239− set_freezable();
240− allow_signal(SIGHUP);
241−
242− for(;;) {
243−
244− set_current_state(TASK_INTERRUPTIBLE);
245−
246− if (td->opcode > 0) {
247− set_current_state(TASK_RUNNING);
248− ret = handle_op(td, 0);
249− set_current_state(TASK_INTERRUPTIBLE);
250− td->opcode = ret;
251− }
252−
253− /* Wait for the next command to be executed */
254− schedule();
255− try_to_freeze();
256−
257− if (signal_pending(current))
258− flush_signals(current);
259−
260− if(kthread_should_stop())
261− break;
262− }
263− return 0;
264−}
265−
266−/**
267− * sysfs_test_command - interface for test commands
268− * @dev: thread reference
269− * @buf: command for actual step
270− * @count: length of buffer
271− *
272− * command syntax:
273− *
274− * opcode:data
275− */
276−static ssize_t sysfs_test_command(struct device *dev, struct device_attribute *attr,
277− const char *buf, size_t count)
278−{
279− struct sched_param schedpar;
280− struct test_thread_data *td;
281− char cmdbuf[32];
282− int op, dat, tid, ret;
283−
284− td = container_of(dev, struct test_thread_data, dev);
285− tid = td->dev.id;
286−
287− /* strings from sysfs write are not 0 terminated! */
288− if (count >= sizeof(cmdbuf))
289− return -EINVAL;
290−
291− /* strip of \n: */
292− if (buf[count-1] == '\n')
293− count--;
294− if (count < 1)
295− return -EINVAL;
296−
297− memcpy(cmdbuf, buf, count);
298− cmdbuf[count] = 0;
299−
300− if (sscanf(cmdbuf, "%d:%d", &op, &dat) != 2)
301− return -EINVAL;
302−
303− switch (op) {
304− case RTTEST_SCHEDOT:
305− schedpar.sched_priority = 0;
306− ret = sched_setscheduler(threads[tid], SCHED_NORMAL, &schedpar);
307− if (ret)
308− return ret;
309− set_user_nice(current, 0);
310− break;
311−
312− case RTTEST_SCHEDRT:
313− schedpar.sched_priority = dat;
314− ret = sched_setscheduler(threads[tid], SCHED_FIFO, &schedpar);
315− if (ret)
316− return ret;
317− break;
318−
319− case RTTEST_SIGNAL:
320− send_sig(SIGHUP, threads[tid], 0);
321− break;
322−
323− default:
324− if (td->opcode > 0)
325− return -EBUSY;
326− td->opdata = dat;
327− td->opcode = op;
328− wake_up_process(threads[tid]);
329− }
330−
331− return count;
332−}
333−
334−/**
335− * sysfs_test_status - sysfs interface for rt tester
336− * @dev: thread to query
337− * @buf: char buffer to be filled with thread status info
338− */
339−static ssize_t sysfs_test_status(struct device *dev, struct device_attribute *attr,
340− char *buf)
341−{
342− struct test_thread_data *td;
343− struct task_struct *tsk;
344− char *curr = buf;
345− int i;
346−
347− td = container_of(dev, struct test_thread_data, dev);
348− tsk = threads[td->dev.id];
349−
350− spin_lock(&rttest_lock);
351−
352− curr += sprintf(curr,
353− "O: %4d, E:%8d, S: 0x%08lx, P: %4d, N: %4d, B: %p, M:",
354− td->opcode, td->event, tsk->state,
355− (MAX_RT_PRIO - 1) - tsk->prio,
356− (MAX_RT_PRIO - 1) - tsk->normal_prio,
357− tsk->pi_blocked_on);
358−
359− for (i = MAX_RT_TEST_MUTEXES - 1; i >=0 ; i--)
360− curr += sprintf(curr, "%d", td->mutexes[i]);
361−
362− spin_unlock(&rttest_lock);
363−
364− curr += sprintf(curr, ", T: %p, R: %p\n", tsk,
365− mutexes[td->dev.id].owner);
366−
367− return curr - buf;
368−}
369−
370−static DEVICE_ATTR(status, S_IRUSR, sysfs_test_status, NULL);
371−static DEVICE_ATTR(command, S_IWUSR, NULL, sysfs_test_command);
372−
373−static struct bus_type rttest_subsys = {
374− .name = "rttest",
375− .dev_name = "rttest",
376−};
377−
378−static int init_test_thread(int id)
379−{
380− thread_data[id].dev.bus = &rttest_subsys;
381− thread_data[id].dev.id = id;
382−
383− threads[id] = kthread_run(test_func, &thread_data[id], "rt-test-%d", id);
384− if (IS_ERR(threads[id]))
385− return PTR_ERR(threads[id]);
386−
387− return device_register(&thread_data[id].dev);
388−}
389−
390−static int init_rttest(void)
391−{
392− int ret, i;
393−
394− spin_lock_init(&rttest_lock);
395−
396− for (i = 0; i < MAX_RT_TEST_MUTEXES; i++)
397− rt_mutex_init(&mutexes[i]);
398−
399− ret = subsys_system_register(&rttest_subsys, NULL);
400− if (ret)
401− return ret;
402−
403− for (i = 0; i < MAX_RT_TEST_THREADS; i++) {
404− ret = init_test_thread(i);
405− if (ret)
406− break;
407− ret = device_create_file(&thread_data[i].dev, &dev_attr_status);
408− if (ret)
409− break;
410− ret = device_create_file(&thread_data[i].dev, &dev_attr_command);
411− if (ret)
412− break;
413− }
414−
415− printk("Initializing RT-Tester: %s\n", ret ? "Failed" : "OK" );
416−
417− return ret;
418−}
419−
420−device_initcall(init_rttest);
kernel/locking/rtmutex.c+1−1
@@ -1120,7 +1120,7 @@ __rt_mutex_slowlock(struct rt_mutex *lock, int state, · 1119 unmodified lines
11201120
11211121 debug_rt_mutex_print_deadlock(waiter);
11221122
1123− schedule_rt_mutex(lock);
1123+ schedule();
11241124
11251125 raw_spin_lock(&lock->wait_lock);
11261126 set_current_state(state);
kernel/locking/rtmutex_common.h+0−22
@@ -14,28 +14,6 @@ · 13 unmodified lines
1414
1515 #include <linux/rtmutex.h>
1616
17−/*
18− * The rtmutex in kernel tester is independent of rtmutex debugging. We
19− * call schedule_rt_mutex_test() instead of schedule() for the tasks which
20− * belong to the tester. That way we can delay the wakeup path of those
21− * threads to provoke lock stealing and testing of complex boosting scenarios.
22− */
23−#ifdef CONFIG_RT_MUTEX_TESTER
24−
25−extern void schedule_rt_mutex_test(struct rt_mutex *lock);
26−
27−#define schedule_rt_mutex(_lock) \
28− do { \
29− if (!(current->flags & PF_MUTEX_TESTER)) \
30− schedule(); \
31− else \
32− schedule_rt_mutex_test(_lock); \
33− } while (0)
34−
35−#else
36−# define schedule_rt_mutex(_lock) schedule()
37−#endif
38−
3917 /*
4018 * This is the control structure for tasks blocked on a rt_mutex,
4119 * which is allocated on the kernel stack on of the blocked task.
kernel/sched/core.c+2−4
@@ -164,14 +164,12 @@ struct static_key sched_feat_keys[__SCHED_FEAT_NR] = { · 163 unmodified lines
164164
165165 static void sched_feat_disable(int i)
166166 {
167− if (static_key_enabled(&sched_feat_keys[i]))
168− static_key_slow_dec(&sched_feat_keys[i]);
167+ static_key_disable(&sched_feat_keys[i]);
169168 }
170169
171170 static void sched_feat_enable(int i)
172171 {
173− if (!static_key_enabled(&sched_feat_keys[i]))
174− static_key_slow_inc(&sched_feat_keys[i]);
172+ static_key_enable(&sched_feat_keys[i]);
175173 }
176174 #else
177175 static void sched_feat_disable(int i) { };
lib/Kconfig.debug+16−6
@@ -916,12 +916,6 @@ config DEBUG_RT_MUTEXES · 915 unmodified lines
916916 This allows rt mutex semantics violations and rt mutex related
917917 deadlocks (lockups) to be detected and reported automatically.
918918
919−config RT_MUTEX_TESTER
920− bool "Built-in scriptable tester for rt-mutexes"
921− depends on DEBUG_KERNEL && RT_MUTEXES && BROKEN
922− help
923− This option enables a rt-mutex tester.
924−
925919 config DEBUG_SPINLOCK
926920 bool "Spinlock and rw-lock debugging: basic checks"
927921 depends on DEBUG_KERNEL
@@ -1528,6 +1522,13 @@ config FAIL_MMC_REQUEST · 600 unmodified lines
15281522 and to test how the mmc host driver handles retries from
15291523 the block device.
15301524
1525+config FAIL_FUTEX
1526+ bool "Fault-injection capability for futexes"
1527+ select DEBUG_FS
1528+ depends on FAULT_INJECTION && FUTEX
1529+ help
1530+ Provide fault-injection capability for futexes.
1531+
15311532 config FAULT_INJECTION_DEBUG_FS
15321533 bool "Debugfs entries for fault-injection capabilities"
15331534 depends on FAULT_INJECTION && SYSFS && DEBUG_FS
@@ -1826,6 +1827,15 @@ config MEMTEST · 292 unmodified lines
18261827 memtest=17, mean do 17 test patterns.
18271828 If you are unsure how to answer this question, answer N.
18281829
1830+config TEST_STATIC_KEYS
1831+ tristate "Test static keys"
1832+ default n
1833+ depends on m
1834+ help
1835+ Test the static key interfaces.
1836+
1837+ If unsure, say N.
1838+
18291839 source "samples/Kconfig"
18301840
18311841 source "lib/Kconfig.kgdb"
lib/Makefile+2−0
@@ -39,6 +39,8 @@ obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o · 38 unmodified lines
3939 obj-$(CONFIG_TEST_LKM) += test_module.o
4040 obj-$(CONFIG_TEST_RHASHTABLE) += test_rhashtable.o
4141 obj-$(CONFIG_TEST_USER_COPY) += test_user_copy.o
42+obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_keys.o
43+obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_key_base.o
4244
4345 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
4446 CFLAGS_kobject.o += -DDEBUG
lib/atomic64.c+3−0
@@ -102,6 +102,9 @@ EXPORT_SYMBOL(atomic64_##op##_return); · 101 unmodified lines
102102
103103 ATOMIC64_OPS(add, +=)
104104 ATOMIC64_OPS(sub, -=)
105+ATOMIC64_OP(and, &=)
106+ATOMIC64_OP(or, |=)
107+ATOMIC64_OP(xor, ^=)
105108
106109 #undef ATOMIC64_OPS
107110 #undef ATOMIC64_OP_RETURN
lib/atomic64_test.c+47−21
@@ -16,8 +16,39 @@ · 15 unmodified lines
1616 #include <linux/kernel.h>
1717 #include <linux/atomic.h>
1818
19+#define TEST(bit, op, c_op, val) \
20+do { \
21+ atomic##bit##_set(&v, v0); \
22+ r = v0; \
23+ atomic##bit##_##op(val, &v); \
24+ r c_op val; \
25+ WARN(atomic##bit##_read(&v) != r, "%Lx != %Lx\n", \
26+ (unsigned long long)atomic##bit##_read(&v), \
27+ (unsigned long long)r); \
28+} while (0)
29+
30+static __init void test_atomic(void)
31+{
32+ int v0 = 0xaaa31337;
33+ int v1 = 0xdeadbeef;
34+ int onestwos = 0x11112222;
35+ int one = 1;
36+
37+ atomic_t v;
38+ int r;
39+
40+ TEST(, add, +=, onestwos);
41+ TEST(, add, +=, -one);
42+ TEST(, sub, -=, onestwos);
43+ TEST(, sub, -=, -one);
44+ TEST(, or, |=, v1);
45+ TEST(, and, &=, v1);
46+ TEST(, xor, ^=, v1);
47+ TEST(, andnot, &= ~, v1);
48+}
49+
1950 #define INIT(c) do { atomic64_set(&v, c); r = c; } while (0)
20−static __init int test_atomic64(void)
51+static __init void test_atomic64(void)
2152 {
2253 long long v0 = 0xaaa31337c001d00dLL;
2354 long long v1 = 0xdeadbeefdeafcafeLL;
@@ -34,15 +65,14 @@ static __init int test_atomic64(void) · 10 unmodified lines
3465 BUG_ON(v.counter != r);
3566 BUG_ON(atomic64_read(&v) != r);
3667
37− INIT(v0);
38− atomic64_add(onestwos, &v);
39− r += onestwos;
40− BUG_ON(v.counter != r);
41−
42− INIT(v0);
43− atomic64_add(-one, &v);
44− r += -one;
45− BUG_ON(v.counter != r);
68+ TEST(64, add, +=, onestwos);
69+ TEST(64, add, +=, -one);
70+ TEST(64, sub, -=, onestwos);
71+ TEST(64, sub, -=, -one);
72+ TEST(64, or, |=, v1);
73+ TEST(64, and, &=, v1);
74+ TEST(64, xor, ^=, v1);
75+ TEST(64, andnot, &= ~, v1);
4676
4777 INIT(v0);
4878 r += onestwos;
@@ -54,16 +84,6 @@ static __init int test_atomic64(void) · 5 unmodified lines
5484 BUG_ON(atomic64_add_return(-one, &v) != r);
5585 BUG_ON(v.counter != r);
5686
57− INIT(v0);
58− atomic64_sub(onestwos, &v);
59− r -= onestwos;
60− BUG_ON(v.counter != r);
61−
62− INIT(v0);
63− atomic64_sub(-one, &v);
64− r -= -one;
65− BUG_ON(v.counter != r);
66−
6787 INIT(v0);
6888 r -= onestwos;
6989 BUG_ON(atomic64_sub_return(onestwos, &v) != r);
@@ -147,6 +167,12 @@ static __init int test_atomic64(void) · 77 unmodified lines
147167 BUG_ON(!atomic64_inc_not_zero(&v));
148168 r += one;
149169 BUG_ON(v.counter != r);
170+}
171+
172+static __init int test_atomics(void)
173+{
174+ test_atomic();
175+ test_atomic64();
150176
151177 #ifdef CONFIG_X86
152178 pr_info("passed for %s platform %s CX8 and %s SSE\n",
@@ -166,4 +192,4 @@ static __init int test_atomic64(void) · 13 unmodified lines
166192 return 0;
167193 }
168194
169−core_initcall(test_atomic64);
195+core_initcall(test_atomics);
lib/lockref.c+0−8
@@ -3,14 +3,6 @@ · 2 unmodified lines
33
44 #if USE_CMPXCHG_LOCKREF
55
6−/*
7− * Allow weakly-ordered memory architectures to provide barrier-less
8− * cmpxchg semantics for lockref updates.
9− */
10−#ifndef cmpxchg64_relaxed
11−# define cmpxchg64_relaxed cmpxchg64
12−#endif
13−
146 /*
157 * Note that the "cmpxchg()" reloads the "old" value for the
168 * failure case.
lib/test_static_key_base.c+68−0
@@ -0,0 +1,68 @@
1+/*
2+ * Kernel module for testing static keys.
3+ *
4+ * Copyright 2015 Akamai Technologies Inc. All Rights Reserved
5+ *
6+ * Authors:
7+ * Jason Baron <jbaron@akamai.com>
8+ *
9+ * This software is licensed under the terms of the GNU General Public
10+ * License version 2, as published by the Free Software Foundation, and
11+ * may be copied, distributed, and modified under those terms.
12+ *
13+ * This program is distributed in the hope that it will be useful,
14+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+ * GNU General Public License for more details.
17+ */
18+
19+#include <linux/module.h>
20+#include <linux/jump_label.h>
21+
22+/* old keys */
23+struct static_key base_old_true_key = STATIC_KEY_INIT_TRUE;
24+EXPORT_SYMBOL_GPL(base_old_true_key);
25+struct static_key base_inv_old_true_key = STATIC_KEY_INIT_TRUE;
26+EXPORT_SYMBOL_GPL(base_inv_old_true_key);
27+struct static_key base_old_false_key = STATIC_KEY_INIT_FALSE;
28+EXPORT_SYMBOL_GPL(base_old_false_key);
29+struct static_key base_inv_old_false_key = STATIC_KEY_INIT_FALSE;
30+EXPORT_SYMBOL_GPL(base_inv_old_false_key);
31+
32+/* new keys */
33+DEFINE_STATIC_KEY_TRUE(base_true_key);
34+EXPORT_SYMBOL_GPL(base_true_key);
35+DEFINE_STATIC_KEY_TRUE(base_inv_true_key);
36+EXPORT_SYMBOL_GPL(base_inv_true_key);
37+DEFINE_STATIC_KEY_FALSE(base_false_key);
38+EXPORT_SYMBOL_GPL(base_false_key);
39+DEFINE_STATIC_KEY_FALSE(base_inv_false_key);
40+EXPORT_SYMBOL_GPL(base_inv_false_key);
41+
42+static void invert_key(struct static_key *key)
43+{
44+ if (static_key_enabled(key))
45+ static_key_disable(key);
46+ else
47+ static_key_enable(key);
48+}
49+
50+static int __init test_static_key_base_init(void)
51+{
52+ invert_key(&base_inv_old_true_key);
53+ invert_key(&base_inv_old_false_key);
54+ invert_key(&base_inv_true_key.key);
55+ invert_key(&base_inv_false_key.key);
56+
57+ return 0;
58+}
59+
60+static void __exit test_static_key_base_exit(void)
61+{
62+}
63+
64+module_init(test_static_key_base_init);
65+module_exit(test_static_key_base_exit);
66+
67+MODULE_AUTHOR("Jason Baron <jbaron@akamai.com>");
68+MODULE_LICENSE("GPL");
lib/test_static_keys.c+225−0
@@ -0,0 +1,225 @@
1+/*
2+ * Kernel module for testing static keys.
3+ *
4+ * Copyright 2015 Akamai Technologies Inc. All Rights Reserved
5+ *
6+ * Authors:
7+ * Jason Baron <jbaron@akamai.com>
8+ *
9+ * This software is licensed under the terms of the GNU General Public
10+ * License version 2, as published by the Free Software Foundation, and
11+ * may be copied, distributed, and modified under those terms.
12+ *
13+ * This program is distributed in the hope that it will be useful,
14+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+ * GNU General Public License for more details.
17+ */
18+
19+#include <linux/module.h>
20+#include <linux/jump_label.h>
21+
22+/* old keys */
23+struct static_key old_true_key = STATIC_KEY_INIT_TRUE;
24+struct static_key old_false_key = STATIC_KEY_INIT_FALSE;
25+
26+/* new api */
27+DEFINE_STATIC_KEY_TRUE(true_key);
28+DEFINE_STATIC_KEY_FALSE(false_key);
29+
30+/* external */
31+extern struct static_key base_old_true_key;
32+extern struct static_key base_inv_old_true_key;
33+extern struct static_key base_old_false_key;
34+extern struct static_key base_inv_old_false_key;
35+
36+/* new api */
37+extern struct static_key_true base_true_key;
38+extern struct static_key_true base_inv_true_key;
39+extern struct static_key_false base_false_key;
40+extern struct static_key_false base_inv_false_key;
41+
42+
43+struct test_key {
44+ bool init_state;
45+ struct static_key *key;
46+ bool (*test_key)(void);
47+};
48+
49+#define test_key_func(key, branch) \
50+ ({bool func(void) { return branch(key); } func; })
51+
52+static void invert_key(struct static_key *key)
53+{
54+ if (static_key_enabled(key))
55+ static_key_disable(key);
56+ else
57+ static_key_enable(key);
58+}
59+
60+static void invert_keys(struct test_key *keys, int size)
61+{
62+ struct static_key *previous = NULL;
63+ int i;
64+
65+ for (i = 0; i < size; i++) {
66+ if (previous != keys[i].key) {
67+ invert_key(keys[i].key);
68+ previous = keys[i].key;
69+ }
70+ }
71+}
72+
73+static int verify_keys(struct test_key *keys, int size, bool invert)
74+{
75+ int i;
76+ bool ret, init;
77+
78+ for (i = 0; i < size; i++) {
79+ ret = static_key_enabled(keys[i].key);
80+ init = keys[i].init_state;
81+ if (ret != (invert ? !init : init))
82+ return -EINVAL;
83+ ret = keys[i].test_key();
84+ if (static_key_enabled(keys[i].key)) {
85+ if (!ret)
86+ return -EINVAL;
87+ } else {
88+ if (ret)
89+ return -EINVAL;
90+ }
91+ }
92+ return 0;
93+}
94+
95+static int __init test_static_key_init(void)
96+{
97+ int ret;
98+ int size;
99+
100+ struct test_key static_key_tests[] = {
101+ /* internal keys - old keys */
102+ {
103+ .init_state = true,
104+ .key = &old_true_key,
105+ .test_key = test_key_func(&old_true_key, static_key_true),
106+ },
107+ {
108+ .init_state = false,
109+ .key = &old_false_key,
110+ .test_key = test_key_func(&old_false_key, static_key_false),
111+ },
112+ /* internal keys - new keys */
113+ {
114+ .init_state = true,
115+ .key = &true_key.key,
116+ .test_key = test_key_func(&true_key, static_branch_likely),
117+ },
118+ {
119+ .init_state = true,
120+ .key = &true_key.key,
121+ .test_key = test_key_func(&true_key, static_branch_unlikely),
122+ },
123+ {
124+ .init_state = false,
125+ .key = &false_key.key,
126+ .test_key = test_key_func(&false_key, static_branch_likely),
127+ },
128+ {
129+ .init_state = false,
130+ .key = &false_key.key,
131+ .test_key = test_key_func(&false_key, static_branch_unlikely),
132+ },
133+ /* external keys - old keys */
134+ {
135+ .init_state = true,
136+ .key = &base_old_true_key,
137+ .test_key = test_key_func(&base_old_true_key, static_key_true),
138+ },
139+ {
140+ .init_state = false,
141+ .key = &base_inv_old_true_key,
142+ .test_key = test_key_func(&base_inv_old_true_key, static_key_true),
143+ },
144+ {
145+ .init_state = false,
146+ .key = &base_old_false_key,
147+ .test_key = test_key_func(&base_old_false_key, static_key_false),
148+ },
149+ {
150+ .init_state = true,
151+ .key = &base_inv_old_false_key,
152+ .test_key = test_key_func(&base_inv_old_false_key, static_key_false),
153+ },
154+ /* external keys - new keys */
155+ {
156+ .init_state = true,
157+ .key = &base_true_key.key,
158+ .test_key = test_key_func(&base_true_key, static_branch_likely),
159+ },
160+ {
161+ .init_state = true,
162+ .key = &base_true_key.key,
163+ .test_key = test_key_func(&base_true_key, static_branch_unlikely),
164+ },
165+ {
166+ .init_state = false,
167+ .key = &base_inv_true_key.key,
168+ .test_key = test_key_func(&base_inv_true_key, static_branch_likely),
169+ },
170+ {
171+ .init_state = false,
172+ .key = &base_inv_true_key.key,
173+ .test_key = test_key_func(&base_inv_true_key, static_branch_unlikely),
174+ },
175+ {
176+ .init_state = false,
177+ .key = &base_false_key.key,
178+ .test_key = test_key_func(&base_false_key, static_branch_likely),
179+ },
180+ {
181+ .init_state = false,
182+ .key = &base_false_key.key,
183+ .test_key = test_key_func(&base_false_key, static_branch_unlikely),
184+ },
185+ {
186+ .init_state = true,
187+ .key = &base_inv_false_key.key,
188+ .test_key = test_key_func(&base_inv_false_key, static_branch_likely),
189+ },
190+ {
191+ .init_state = true,
192+ .key = &base_inv_false_key.key,
193+ .test_key = test_key_func(&base_inv_false_key, static_branch_unlikely),
194+ },
195+ };
196+
197+ size = ARRAY_SIZE(static_key_tests);
198+
199+ ret = verify_keys(static_key_tests, size, false);
200+ if (ret)
201+ goto out;
202+
203+ invert_keys(static_key_tests, size);
204+ ret = verify_keys(static_key_tests, size, true);
205+ if (ret)
206+ goto out;
207+
208+ invert_keys(static_key_tests, size);
209+ ret = verify_keys(static_key_tests, size, false);
210+ if (ret)
211+ goto out;
212+ return 0;
213+out:
214+ return ret;
215+}
216+
217+static void __exit test_static_key_exit(void)
218+{
219+}
220+
221+module_init(test_static_key_init);
222+module_exit(test_static_key_exit);
223+
224+MODULE_AUTHOR("Jason Baron <jbaron@akamai.com>");
225+MODULE_LICENSE("GPL");
scripts/rt-tester/check-all.sh+0−21
@@ -1,21 +0,0 @@
1−
2−
3−function testit ()
4−{
5− printf "%-30s: " $1
6− ./rt-tester.py $1 | grep Pass
7−}
8−
9−testit t2-l1-2rt-sameprio.tst
10−testit t2-l1-pi.tst
11−testit t2-l1-signal.tst
12−#testit t2-l2-2rt-deadlock.tst
13−testit t3-l1-pi-1rt.tst
14−testit t3-l1-pi-2rt.tst
15−testit t3-l1-pi-3rt.tst
16−testit t3-l1-pi-signal.tst
17−testit t3-l1-pi-steal.tst
18−testit t3-l2-pi.tst
19−testit t4-l2-pi-deboost.tst
20−testit t5-l4-pi-boost-deboost.tst
21−testit t5-l4-pi-boost-deboost-setsched.tst
scripts/rt-tester/rt-tester.py+0−218
@@ -1,218 +0,0 @@
1−#!/usr/bin/python
2−#
3−# rt-mutex tester
4−#
5−# (C) 2006 Thomas Gleixner <tglx@linutronix.de>
6−#
7−# This program is free software; you can redistribute it and/or modify
8−# it under the terms of the GNU General Public License version 2 as
9−# published by the Free Software Foundation.
10−#
11−import os
12−import sys
13−import getopt
14−import shutil
15−import string
16−
17−# Globals
18−quiet = 0
19−test = 0
20−comments = 0
21−
22−sysfsprefix = "/sys/devices/system/rttest/rttest"
23−statusfile = "/status"
24−commandfile = "/command"
25−
26−# Command opcodes
27−cmd_opcodes = {
28− "schedother" : "1",
29− "schedfifo" : "2",
30− "lock" : "3",
31− "locknowait" : "4",
32− "lockint" : "5",
33− "lockintnowait" : "6",
34− "lockcont" : "7",
35− "unlock" : "8",
36− "signal" : "11",
37− "resetevent" : "98",
38− "reset" : "99",
39− }
40−
41−test_opcodes = {
42− "prioeq" : ["P" , "eq" , None],
43− "priolt" : ["P" , "lt" , None],
44− "priogt" : ["P" , "gt" , None],
45− "nprioeq" : ["N" , "eq" , None],
46− "npriolt" : ["N" , "lt" , None],
47− "npriogt" : ["N" , "gt" , None],
48− "unlocked" : ["M" , "eq" , 0],
49− "trylock" : ["M" , "eq" , 1],
50− "blocked" : ["M" , "eq" , 2],
51− "blockedwake" : ["M" , "eq" , 3],
52− "locked" : ["M" , "eq" , 4],
53− "opcodeeq" : ["O" , "eq" , None],
54− "opcodelt" : ["O" , "lt" , None],
55− "opcodegt" : ["O" , "gt" , None],
56− "eventeq" : ["E" , "eq" , None],
57− "eventlt" : ["E" , "lt" , None],
58− "eventgt" : ["E" , "gt" , None],
59− }
60−
61−# Print usage information
62−def usage():
63− print "rt-tester.py <-c -h -q -t> <testfile>"
64− print " -c display comments after first command"
65− print " -h help"
66− print " -q quiet mode"
67− print " -t test mode (syntax check)"
68− print " testfile: read test specification from testfile"
69− print " otherwise from stdin"
70− return
71−
72−# Print progress when not in quiet mode
73−def progress(str):
74− if not quiet:
75− print str
76−
77−# Analyse a status value
78−def analyse(val, top, arg):
79−
80− intval = int(val)
81−
82− if top[0] == "M":
83− intval = intval / (10 ** int(arg))
84− intval = intval % 10
85− argval = top[2]
86− elif top[0] == "O":
87− argval = int(cmd_opcodes.get(arg, arg))
88− else:
89− argval = int(arg)
90−
91− # progress("%d %s %d" %(intval, top[1], argval))
92−
93− if top[1] == "eq" and intval == argval:
94− return 1
95− if top[1] == "lt" and intval < argval:
96− return 1
97− if top[1] == "gt" and intval > argval:
98− return 1
99− return 0
100−
101−# Parse the commandline
102−try:
103− (options, arguments) = getopt.getopt(sys.argv[1:],'chqt')
104−except getopt.GetoptError, ex:
105− usage()
106− sys.exit(1)
107−
108−# Parse commandline options
109−for option, value in options:
110− if option == "-c":
111− comments = 1
112− elif option == "-q":
113− quiet = 1
114− elif option == "-t":
115− test = 1
116− elif option == '-h':
117− usage()
118− sys.exit(0)
119−
120−# Select the input source
121−if arguments:
122− try:
123− fd = open(arguments[0])
124− except Exception,ex:
125− sys.stderr.write("File not found %s\n" %(arguments[0]))
126− sys.exit(1)
127−else:
128− fd = sys.stdin
129−
130−linenr = 0
131−
132−# Read the test patterns
133−while 1:
134−
135− linenr = linenr + 1
136− line = fd.readline()
137− if not len(line):
138− break
139−
140− line = line.strip()
141− parts = line.split(":")
142−
143− if not parts or len(parts) < 1:
144− continue
145−
146− if len(parts[0]) == 0:
147− continue
148−
149− if parts[0].startswith("#"):
150− if comments > 1:
151− progress(line)
152− continue
153−
154− if comments == 1:
155− comments = 2
156−
157− progress(line)
158−
159− cmd = parts[0].strip().lower()
160− opc = parts[1].strip().lower()
161− tid = parts[2].strip()
162− dat = parts[3].strip()
163−
164− try:
165− # Test or wait for a status value
166− if cmd == "t" or cmd == "w":
167− testop = test_opcodes[opc]
168−
169− fname = "%s%s%s" %(sysfsprefix, tid, statusfile)
170− if test:
171− print fname
172− continue
173−
174− while 1:
175− query = 1
176− fsta = open(fname, 'r')
177− status = fsta.readline().strip()
178− fsta.close()
179− stat = status.split(",")
180− for s in stat:
181− s = s.strip()
182− if s.startswith(testop[0]):
183− # Separate status value
184− val = s[2:].strip()
185− query = analyse(val, testop, dat)
186− break
187− if query or cmd == "t":
188− break
189−
190− progress(" " + status)
191−
192− if not query:
193− sys.stderr.write("Test failed in line %d\n" %(linenr))
194− sys.exit(1)
195−
196− # Issue a command to the tester
197− elif cmd == "c":
198− cmdnr = cmd_opcodes[opc]
199− # Build command string and sys filename
200− cmdstr = "%s:%s" %(cmdnr, dat)
201− fname = "%s%s%s" %(sysfsprefix, tid, commandfile)
202− if test:
203− print fname
204− continue
205− fcmd = open(fname, 'w')
206− fcmd.write(cmdstr)
207− fcmd.close()
208−
209− except Exception,ex:
210− sys.stderr.write(str(ex))
211− sys.stderr.write("\nSyntax error in line %d\n" %(linenr))
212− if not test:
213− fd.close()
214− sys.exit(1)
215−
216−# Normal exit pass
217−print "Pass"
218−sys.exit(0)
scripts/rt-tester/t2-l1-2rt-sameprio.tst+0−94
@@ -1,94 +0,0 @@
1−#
2−# RT-Mutex test
3−#
4−# Op: C(ommand)/T(est)/W(ait)
5−# | opcode
6−# | | threadid: 0-7
7−# | | | opcode argument
8−# | | | |
9−# C: lock: 0: 0
10−#
11−# Commands
12−#
13−# opcode opcode argument
14−# schedother nice value
15−# schedfifo priority
16−# lock lock nr (0-7)
17−# locknowait lock nr (0-7)
18−# lockint lock nr (0-7)
19−# lockintnowait lock nr (0-7)
20−# lockcont lock nr (0-7)
21−# unlock lock nr (0-7)
22−# signal 0
23−# reset 0
24−# resetevent 0
25−#
26−# Tests / Wait
27−#
28−# opcode opcode argument
29−#
30−# prioeq priority
31−# priolt priority
32−# priogt priority
33−# nprioeq normal priority
34−# npriolt normal priority
35−# npriogt normal priority
36−# locked lock nr (0-7)
37−# blocked lock nr (0-7)
38−# blockedwake lock nr (0-7)
39−# unlocked lock nr (0-7)
40−# opcodeeq command opcode or number
41−# opcodelt number
42−# opcodegt number
43−# eventeq number
44−# eventgt number
45−# eventlt number
46−
47−#
48−# 2 threads 1 lock
49−#
50−C: resetevent: 0: 0
51−W: opcodeeq: 0: 0
52−
53−# Set schedulers
54−C: schedfifo: 0: 80
55−C: schedfifo: 1: 80
56−
57−# T0 lock L0
58−C: locknowait: 0: 0
59−C: locknowait: 1: 0
60−W: locked: 0: 0
61−W: blocked: 1: 0
62−T: prioeq: 0: 80
63−
64−# T0 unlock L0
65−C: unlock: 0: 0
66−W: locked: 1: 0
67−
68−# Verify T0
69−W: unlocked: 0: 0
70−T: prioeq: 0: 80
71−
72−# Unlock
73−C: unlock: 1: 0
74−W: unlocked: 1: 0
75−
76−# T1,T0 lock L0
77−C: locknowait: 1: 0
78−C: locknowait: 0: 0
79−W: locked: 1: 0
80−W: blocked: 0: 0
81−T: prioeq: 1: 80
82−
83−# T1 unlock L0
84−C: unlock: 1: 0
85−W: locked: 0: 0
86−
87−# Verify T1
88−W: unlocked: 1: 0
89−T: prioeq: 1: 80
90−
91−# Unlock and exit
92−C: unlock: 0: 0
93−W: unlocked: 0: 0
94−
scripts/rt-tester/t2-l1-pi.tst+0−77
@@ -1,77 +0,0 @@
1−#
2−# RT-Mutex test
3−#
4−# Op: C(ommand)/T(est)/W(ait)
5−# | opcode
6−# | | threadid: 0-7
7−# | | | opcode argument
8−# | | | |
9−# C: lock: 0: 0
10−#
11−# Commands
12−#
13−# opcode opcode argument
14−# schedother nice value
15−# schedfifo priority
16−# lock lock nr (0-7)
17−# locknowait lock nr (0-7)
18−# lockint lock nr (0-7)
19−# lockintnowait lock nr (0-7)
20−# lockcont lock nr (0-7)
21−# unlock lock nr (0-7)
22−# signal 0
23−# reset 0
24−# resetevent 0
25−#
26−# Tests / Wait
27−#
28−# opcode opcode argument
29−#
30−# prioeq priority
31−# priolt priority
32−# priogt priority
33−# nprioeq normal priority
34−# npriolt normal priority
35−# npriogt normal priority
36−# locked lock nr (0-7)
37−# blocked lock nr (0-7)
38−# blockedwake lock nr (0-7)
39−# unlocked lock nr (0-7)
40−# opcodeeq command opcode or number
41−# opcodelt number
42−# opcodegt number
43−# eventeq number
44−# eventgt number
45−# eventlt number
46−
47−#
48−# 2 threads 1 lock with priority inversion
49−#
50−C: resetevent: 0: 0
51−W: opcodeeq: 0: 0
52−
53−# Set schedulers
54−C: schedother: 0: 0
55−C: schedfifo: 1: 80
56−
57−# T0 lock L0
58−C: locknowait: 0: 0
59−W: locked: 0: 0
60−
61−# T1 lock L0
62−C: locknowait: 1: 0
63−W: blocked: 1: 0
64−T: prioeq: 0: 80
65−
66−# T0 unlock L0
67−C: unlock: 0: 0
68−W: locked: 1: 0
69−
70−# Verify T1
71−W: unlocked: 0: 0
72−T: priolt: 0: 1
73−
74−# Unlock and exit
75−C: unlock: 1: 0
76−W: unlocked: 1: 0
77−
scripts/rt-tester/t2-l1-signal.tst+0−72
@@ -1,72 +0,0 @@
1−#
2−# RT-Mutex test
3−#
4−# Op: C(ommand)/T(est)/W(ait)
5−# | opcode
6−# | | threadid: 0-7
7−# | | | opcode argument
8−# | | | |
9−# C: lock: 0: 0
10−#
11−# Commands
12−#
13−# opcode opcode argument
14−# schedother nice value
15−# schedfifo priority
16−# lock lock nr (0-7)
17−# locknowait lock nr (0-7)
18−# lockint lock nr (0-7)
19−# lockintnowait lock nr (0-7)
20−# lockcont lock nr (0-7)
21−# unlock lock nr (0-7)
22−# signal 0
23−# reset 0
24−# resetevent 0
25−#
26−# Tests / Wait
27−#
28−# opcode opcode argument
29−#
30−# prioeq priority
31−# priolt priority
32−# priogt priority
33−# nprioeq normal priority
34−# npriolt normal priority
35−# npriogt normal priority
36−# locked lock nr (0-7)
37−# blocked lock nr (0-7)
38−# blockedwake lock nr (0-7)
39−# unlocked lock nr (0-7)
40−# opcodeeq command opcode or number
41−# opcodelt number
42−# opcodegt number
43−# eventeq number
44−# eventgt number
45−# eventlt number
46−
47−#
48−# 2 threads 1 lock with priority inversion
49−#
50−C: resetevent: 0: 0
51−W: opcodeeq: 0: 0
52−
53−# Set schedulers
54−C: schedother: 0: 0
55−C: schedother: 1: 0
56−
57−# T0 lock L0
58−C: locknowait: 0: 0
59−W: locked: 0: 0
60−
61−# T1 lock L0
62−C: lockintnowait: 1: 0
63−W: blocked: 1: 0
64−
65−# Interrupt T1
66−C: signal: 1: 0
67−W: unlocked: 1: 0
68−T: opcodeeq: 1: -4
69−
70−# Unlock and exit
71−C: unlock: 0: 0
72−W: unlocked: 0: 0
scripts/rt-tester/t2-l2-2rt-deadlock.tst+0−84
@@ -1,84 +0,0 @@
1−#
2−# RT-Mutex test
3−#
4−# Op: C(ommand)/T(est)/W(ait)
5−# | opcode
6−# | | threadid: 0-7
7−# | | | opcode argument
8−# | | | |
9−# C: lock: 0: 0
10−#
11−# Commands
12−#
13−# opcode opcode argument
14−# schedother nice value
15−# schedfifo priority
16−# lock lock nr (0-7)
17−# locknowait lock nr (0-7)
18−# lockint lock nr (0-7)
19−# lockintnowait lock nr (0-7)
20−# lockcont lock nr (0-7)
21−# unlock lock nr (0-7)
22−# signal 0
23−# reset 0
24−# resetevent 0
25−#
26−# Tests / Wait
27−#
28−# opcode opcode argument
29−#
30−# prioeq priority
31−# priolt priority
32−# priogt priority
33−# nprioeq normal priority
34−# npriolt normal priority
35−# npriogt normal priority
36−# locked lock nr (0-7)
37−# blocked lock nr (0-7)
38−# blockedwake lock nr (0-7)
39−# unlocked lock nr (0-7)
40−# opcodeeq command opcode or number
41−# opcodelt number
42−# opcodegt number
43−# eventeq number
44−# eventgt number
45−# eventlt number
46−
47−#
48−# 2 threads 2 lock
49−#
50−C: resetevent: 0: 0
51−W: opcodeeq: 0: 0
52−
53−# Set schedulers
54−C: schedfifo: 0: 80
55−C: schedfifo: 1: 80
56−
57−# T0 lock L0
58−C: locknowait: 0: 0
59−W: locked: 0: 0
60−
61−# T1 lock L1
62−C: locknowait: 1: 1
63−W: locked: 1: 1
64−
65−# T0 lock L1
66−C: lockintnowait: 0: 1
67−W: blocked: 0: 1
68−
69−# T1 lock L0
70−C: lockintnowait: 1: 0
71−W: blocked: 1: 0
72−
73−# Make deadlock go away
74−C: signal: 1: 0
75−W: unlocked: 1: 0
76−C: signal: 0: 0
77−W: unlocked: 0: 1
78−
79−# Unlock and exit
80−C: unlock: 0: 0
81−W: unlocked: 0: 0
82−C: unlock: 1: 1
83−W: unlocked: 1: 1
84−
scripts/rt-tester/t3-l1-pi-1rt.tst+0−87
@@ -1,87 +0,0 @@
1−#
2−# rt-mutex test
3−#
4−# Op: C(ommand)/T(est)/W(ait)
5−# | opcode
6−# | | threadid: 0-7
7−# | | | opcode argument
8−# | | | |
9−# C: lock: 0: 0
10−#
11−# Commands
12−#
13−# opcode opcode argument
14−# schedother nice value
15−# schedfifo priority
16−# lock lock nr (0-7)
17−# locknowait lock nr (0-7)
18−# lockint lock nr (0-7)
19−# lockintnowait lock nr (0-7)
20−# lockcont lock nr (0-7)
21−# unlock lock nr (0-7)
22−# signal thread to signal (0-7)
23−# reset 0
24−# resetevent 0
25−#
26−# Tests / Wait
27−#
28−# opcode opcode argument
29−#
30−# prioeq priority
31−# priolt priority
32−# priogt priority
33−# nprioeq normal priority
34−# npriolt normal priority
35−# npriogt normal priority
36−# locked lock nr (0-7)
37−# blocked lock nr (0-7)
38−# blockedwake lock nr (0-7)
39−# unlocked lock nr (0-7)
40−# opcodeeq command opcode or number
41−# opcodelt number
42−# opcodegt number
43−# eventeq number
44−# eventgt number
45−# eventlt number
46−
47−#
48−# 3 threads 1 lock PI
49−#
50−C: resetevent: 0: 0
51−W: opcodeeq: 0: 0
52−
53−# Set schedulers
54−C: schedother: 0: 0
55−C: schedother: 1: 0
56−C: schedfifo: 2: 82
57−
58−# T0 lock L0
59−C: locknowait: 0: 0
60−W: locked: 0: 0
61−
62−# T1 lock L0
63−C: locknowait: 1: 0
64−W: blocked: 1: 0
65−T: priolt: 0: 1
66−
67−# T2 lock L0
68−C: locknowait: 2: 0
69−W: blocked: 2: 0
70−T: prioeq: 0: 82
71−
72−# T0 unlock L0
73−C: unlock: 0: 0
74−
75−# Wait until T2 got the lock
76−W: locked: 2: 0
77−W: unlocked: 0: 0
78−T: priolt: 0: 1
79−
80−# T2 unlock L0
81−C: unlock: 2: 0
82−
83−W: unlocked: 2: 0
84−W: locked: 1: 0
85−
86−C: unlock: 1: 0
87−W: unlocked: 1: 0
scripts/rt-tester/t3-l1-pi-2rt.tst+0−88
@@ -1,88 +0,0 @@
1−#
2−# rt-mutex test
3−#
4−# Op: C(ommand)/T(est)/W(ait)
5−# | opcode
6−# | | threadid: 0-7
7−# | | | opcode argument
8−# | | | |
9−# C: lock: 0: 0
10−#
11−# Commands
12−#
13−# opcode opcode argument
14−# schedother nice value
15−# schedfifo priority
16−# lock lock nr (0-7)
17−# locknowait lock nr (0-7)
18−# lockint lock nr (0-7)
19−# lockintnowait lock nr (0-7)
20−# lockcont lock nr (0-7)
21−# unlock lock nr (0-7)
22−# signal thread to signal (0-7)
23−# reset 0
24−# resetevent 0
25−#
26−# Tests / Wait
27−#
28−# opcode opcode argument
29−#
30−# prioeq priority
31−# priolt priority
32−# priogt priority
33−# nprioeq normal priority
34−# npriolt normal priority
35−# npriogt normal priority
36−# locked lock nr (0-7)
37−# blocked lock nr (0-7)
38−# blockedwake lock nr (0-7)
39−# unlocked lock nr (0-7)
40−# opcodeeq command opcode or number
41−# opcodelt number
42−# opcodegt number
43−# eventeq number
44−# eventgt number
45−# eventlt number
46−
47−#
48−# 3 threads 1 lock PI
49−#
50−C: resetevent: 0: 0
51−W: opcodeeq: 0: 0
52−
53−# Set schedulers
54−C: schedother: 0: 0
55−C: schedfifo: 1: 81
56−C: schedfifo: 2: 82
57−
58−# T0 lock L0
59−C: locknowait: 0: 0
60−W: locked: 0: 0
61−
62−# T1 lock L0
63−C: locknowait: 1: 0
64−W: blocked: 1: 0
65−T: prioeq: 0: 81
66−
67−# T2 lock L0
68−C: locknowait: 2: 0
69−W: blocked: 2: 0
70−T: prioeq: 0: 82
71−T: prioeq: 1: 81
72−
73−# T0 unlock L0
74−C: unlock: 0: 0
75−
76−# Wait until T2 got the lock
77−W: locked: 2: 0
78−W: unlocked: 0: 0
79−T: priolt: 0: 1
80−
81−# T2 unlock L0
82−C: unlock: 2: 0
83−
84−W: unlocked: 2: 0
85−W: locked: 1: 0
86−
87−C: unlock: 1: 0
88−W: unlocked: 1: 0
scripts/rt-tester/t3-l1-pi-3rt.tst+0−87
@@ -1,87 +0,0 @@
1−#
2−# rt-mutex test
3−#
4−# Op: C(ommand)/T(est)/W(ait)
5−# | opcode
6−# | | threadid: 0-7
7−# | | | opcode argument
8−# | | | |
9−# C: lock: 0: 0
10−#
11−# Commands
12−#
13−# opcode opcode argument
14−# schedother nice value
15−# schedfifo priority
16−# lock lock nr (0-7)
17−# locknowait lock nr (0-7)
18−# lockint lock nr (0-7)
19−# lockintnowait lock nr (0-7)
20−# lockcont lock nr (0-7)
21−# unlock lock nr (0-7)
22−# signal thread to signal (0-7)
23−# reset 0
24−# resetevent 0
25−#
26−# Tests / Wait
27−#
28−# opcode opcode argument
29−#
30−# prioeq priority
31−# priolt priority
32−# priogt priority
33−# nprioeq normal priority
34−# npriolt normal priority
35−# npriogt normal priority
36−# locked lock nr (0-7)
37−# blocked lock nr (0-7)
38−# blockedwake lock nr (0-7)
39−# unlocked lock nr (0-7)
40−# opcodeeq command opcode or number
41−# opcodelt number
42−# opcodegt number
43−# eventeq number
44−# eventgt number
45−# eventlt number
46−
47−#
48−# 3 threads 1 lock PI
49−#
50−C: resetevent: 0: 0
51−W: opcodeeq: 0: 0
52−
53−# Set schedulers
54−C: schedfifo: 0: 80
55−C: schedfifo: 1: 81
56−C: schedfifo: 2: 82
57−
58−# T0 lock L0
59−C: locknowait: 0: 0
60−W: locked: 0: 0
61−
62−# T1 lock L0
63−C: locknowait: 1: 0
64−W: blocked: 1: 0
65−T: prioeq: 0: 81
66−
67−# T2 lock L0
68−C: locknowait: 2: 0
69−W: blocked: 2: 0
70−T: prioeq: 0: 82
71−
72−# T0 unlock L0
73−C: unlock: 0: 0
74−
75−# Wait until T2 got the lock
76−W: locked: 2: 0
77−W: unlocked: 0: 0
78−T: prioeq: 0: 80
79−
80−# T2 unlock L0
81−C: unlock: 2: 0
82−
83−W: locked: 1: 0
84−W: unlocked: 2: 0
85−
86−C: unlock: 1: 0
87−W: unlocked: 1: 0
scripts/rt-tester/t3-l1-pi-signal.tst+0−93
@@ -1,93 +0,0 @@
1−#
2−# rt-mutex test
3−#
4−# Op: C(ommand)/T(est)/W(ait)
5−# | opcode
6−# | | threadid: 0-7
7−# | | | opcode argument
8−# | | | |
9−# C: lock: 0: 0
10−#
11−# Commands
12−#
13−# opcode opcode argument
14−# schedother nice value
15−# schedfifo priority
16−# lock lock nr (0-7)
17−# locknowait lock nr (0-7)
18−# lockint lock nr (0-7)
19−# lockintnowait lock nr (0-7)
20−# lockcont lock nr (0-7)
21−# unlock lock nr (0-7)
22−# signal thread to signal (0-7)
23−# reset 0
24−# resetevent 0
25−#
26−# Tests / Wait
27−#
28−# opcode opcode argument
29−#
30−# prioeq priority
31−# priolt priority
32−# priogt priority
33−# nprioeq normal priority
34−# npriolt normal priority
35−# npriogt normal priority
36−# locked lock nr (0-7)
37−# blocked lock nr (0-7)
38−# blockedwake lock nr (0-7)
39−# unlocked lock nr (0-7)
40−# opcodeeq command opcode or number
41−# opcodelt number
42−# opcodegt number
43−# eventeq number
44−# eventgt number
45−# eventlt number
46−
47−# Reset event counter
48−C: resetevent: 0: 0
49−W: opcodeeq: 0: 0
50−
51−# Set priorities
52−C: schedother: 0: 0
53−C: schedfifo: 1: 80
54−C: schedfifo: 2: 81
55−
56−# T0 lock L0
57−C: lock: 0: 0
58−W: locked: 0: 0
59−
60−# T1 lock L0, no wait in the wakeup path
61−C: locknowait: 1: 0
62−W: blocked: 1: 0
63−T: prioeq: 0: 80
64−T: prioeq: 1: 80
65−
66−# T2 lock L0 interruptible, no wait in the wakeup path
67−C: lockintnowait: 2: 0
68−W: blocked: 2: 0
69−T: prioeq: 0: 81
70−T: prioeq: 1: 80
71−
72−# Interrupt T2
73−C: signal: 2: 2
74−W: unlocked: 2: 0
75−T: prioeq: 1: 80
76−T: prioeq: 0: 80
77−
78−T: locked: 0: 0
79−T: blocked: 1: 0
80−
81−# T0 unlock L0
82−C: unlock: 0: 0
83−
84−# Wait until T1 has locked L0 and exit
85−W: locked: 1: 0
86−W: unlocked: 0: 0
87−T: priolt: 0: 1
88−
89−C: unlock: 1: 0
90−W: unlocked: 1: 0
91−
92−
93−
scripts/rt-tester/t3-l1-pi-steal.tst+0−91
@@ -1,91 +0,0 @@
1−#
2−# rt-mutex test
3−#
4−# Op: C(ommand)/T(est)/W(ait)
5−# | opcode
6−# | | threadid: 0-7
7−# | | | opcode argument
8−# | | | |
9−# C: lock: 0: 0
10−#
11−# Commands
12−#
13−# opcode opcode argument
14−# schedother nice value
15−# schedfifo priority
16−# lock lock nr (0-7)
17−# locknowait lock nr (0-7)
18−# lockint lock nr (0-7)
19−# lockintnowait lock nr (0-7)
20−# lockcont lock nr (0-7)
21−# unlock lock nr (0-7)
22−# signal thread to signal (0-7)
23−# reset 0
24−# resetevent 0
25−#
26−# Tests / Wait
27−#
28−# opcode opcode argument
29−#
30−# prioeq priority
31−# priolt priority
32−# priogt priority
33−# nprioeq normal priority
34−# npriolt normal priority
35−# npriogt normal priority
36−# locked lock nr (0-7)
37−# blocked lock nr (0-7)
38−# blockedwake lock nr (0-7)
39−# unlocked lock nr (0-7)
40−# opcodeeq command opcode or number
41−# opcodelt number
42−# opcodegt number
43−# eventeq number
44−# eventgt number
45−# eventlt number
46−
47−#
48−# 3 threads 1 lock PI steal pending ownership
49−#
50−C: resetevent: 0: 0
51−W: opcodeeq: 0: 0
52−
53−# Set schedulers
54−C: schedother: 0: 0
55−C: schedfifo: 1: 80
56−C: schedfifo: 2: 81
57−
58−# T0 lock L0
59−C: lock: 0: 0
60−W: locked: 0: 0
61−
62−# T1 lock L0
63−C: lock: 1: 0
64−W: blocked: 1: 0
65−T: prioeq: 0: 80
66−
67−# T0 unlock L0
68−C: unlock: 0: 0
69−
70−# Wait until T1 is in the wakeup loop
71−W: blockedwake: 1: 0
72−T: priolt: 0: 1
73−
74−# T2 lock L0
75−C: lock: 2: 0
76−# T1 leave wakeup loop
77−C: lockcont: 1: 0
78−
79−# T2 must have the lock and T1 must be blocked
80−W: locked: 2: 0
81−W: blocked: 1: 0
82−
83−# T2 unlock L0
84−C: unlock: 2: 0
85−
86−# Wait until T1 is in the wakeup loop and let it run
87−W: blockedwake: 1: 0
88−C: lockcont: 1: 0
89−W: locked: 1: 0
90−C: unlock: 1: 0
91−W: unlocked: 1: 0
scripts/rt-tester/t3-l2-pi.tst+0−87
@@ -1,87 +0,0 @@
1−#
2−# rt-mutex test
3−#
4−# Op: C(ommand)/T(est)/W(ait)
5−# | opcode
6−# | | threadid: 0-7
7−# | | | opcode argument
8−# | | | |
9−# C: lock: 0: 0
10−#
11−# Commands
12−#
13−# opcode opcode argument
14−# schedother nice value
15−# schedfifo priority
16−# lock lock nr (0-7)
17−# locknowait lock nr (0-7)
18−# lockint lock nr (0-7)
19−# lockintnowait lock nr (0-7)
20−# lockcont lock nr (0-7)
21−# unlock lock nr (0-7)
22−# signal thread to signal (0-7)
23−# reset 0
24−# resetevent 0
25−#
26−# Tests / Wait
27−#
28−# opcode opcode argument
29−#
30−# prioeq priority
31−# priolt priority
32−# priogt priority
33−# nprioeq normal priority
34−# npriolt normal priority
35−# npriogt normal priority
36−# locked lock nr (0-7)
37−# blocked lock nr (0-7)
38−# blockedwake lock nr (0-7)
39−# unlocked lock nr (0-7)
40−# opcodeeq command opcode or number
41−# opcodelt number
42−# opcodegt number
43−# eventeq number
44−# eventgt number
45−# eventlt number
46−
47−#
48−# 3 threads 2 lock PI
49−#
50−C: resetevent: 0: 0
51−W: opcodeeq: 0: 0
52−
53−# Set schedulers
54−C: schedother: 0: 0
55−C: schedother: 1: 0
56−C: schedfifo: 2: 82
57−
58−# T0 lock L0
59−C: locknowait: 0: 0
60−W: locked: 0: 0
61−
62−# T1 lock L0
63−C: locknowait: 1: 0
64−W: blocked: 1: 0
65−T: priolt: 0: 1
66−
67−# T2 lock L0
68−C: locknowait: 2: 0
69−W: blocked: 2: 0
70−T: prioeq: 0: 82
71−
72−# T0 unlock L0
73−C: unlock: 0: 0
74−
75−# Wait until T2 got the lock
76−W: locked: 2: 0
77−W: unlocked: 0: 0
78−T: priolt: 0: 1
79−
80−# T2 unlock L0
81−C: unlock: 2: 0
82−
83−W: unlocked: 2: 0
84−W: locked: 1: 0
85−
86−C: unlock: 1: 0
87−W: unlocked: 1: 0
scripts/rt-tester/t4-l2-pi-deboost.tst+0−118
@@ -1,118 +0,0 @@
1−#
2−# rt-mutex test
3−#
4−# Op: C(ommand)/T(est)/W(ait)
5−# | opcode
6−# | | threadid: 0-7
7−# | | | opcode argument
8−# | | | |
9−# C: lock: 0: 0
10−#
11−# Commands
12−#
13−# opcode opcode argument
14−# schedother nice value
15−# schedfifo priority
16−# lock lock nr (0-7)
17−# locknowait lock nr (0-7)
18−# lockint lock nr (0-7)
19−# lockintnowait lock nr (0-7)
20−# lockcont lock nr (0-7)
21−# unlock lock nr (0-7)
22−# signal thread to signal (0-7)
23−# reset 0
24−# resetevent 0
25−#
26−# Tests / Wait
27−#
28−# opcode opcode argument
29−#
30−# prioeq priority
31−# priolt priority
32−# priogt priority
33−# nprioeq normal priority
34−# npriolt normal priority
35−# npriogt normal priority
36−# locked lock nr (0-7)
37−# blocked lock nr (0-7)
38−# blockedwake lock nr (0-7)
39−# unlocked lock nr (0-7)
40−# opcodeeq command opcode or number
41−# opcodelt number
42−# opcodegt number
43−# eventeq number
44−# eventgt number
45−# eventlt number
46−
47−#
48−# 4 threads 2 lock PI
49−#
50−C: resetevent: 0: 0
51−W: opcodeeq: 0: 0
52−
53−# Set schedulers
54−C: schedother: 0: 0
55−C: schedother: 1: 0
56−C: schedfifo: 2: 82
57−C: schedfifo: 3: 83
58−
59−# T0 lock L0
60−C: locknowait: 0: 0
61−W: locked: 0: 0
62−
63−# T1 lock L1
64−C: locknowait: 1: 1
65−W: locked: 1: 1
66−
67−# T3 lock L0
68−C: lockintnowait: 3: 0
69−W: blocked: 3: 0
70−T: prioeq: 0: 83
71−
72−# T0 lock L1
73−C: lock: 0: 1
74−W: blocked: 0: 1
75−T: prioeq: 1: 83
76−
77−# T1 unlock L1
78−C: unlock: 1: 1
79−
80−# Wait until T0 is in the wakeup code
81−W: blockedwake: 0: 1
82−
83−# Verify that T1 is unboosted
84−W: unlocked: 1: 1
85−T: priolt: 1: 1
86−
87−# T2 lock L1 (T0 is boosted and pending owner !)
88−C: locknowait: 2: 1
89−W: blocked: 2: 1
90−T: prioeq: 0: 83
91−
92−# Interrupt T3 and wait until T3 returned
93−C: signal: 3: 0
94−W: unlocked: 3: 0
95−
96−# Verify prio of T0 (still pending owner,
97−# but T2 is enqueued due to the previous boost by T3
98−T: prioeq: 0: 82
99−
100−# Let T0 continue
101−C: lockcont: 0: 1
102−W: locked: 0: 1
103−
104−# Unlock L1 and let T2 get L1
105−C: unlock: 0: 1
106−W: locked: 2: 1
107−
108−# Verify that T0 is unboosted
109−W: unlocked: 0: 1
110−T: priolt: 0: 1
111−
112−# Unlock everything and exit
113−C: unlock: 2: 1
114−W: unlocked: 2: 1
115−
116−C: unlock: 0: 0
117−W: unlocked: 0: 0
118−
scripts/rt-tester/t5-l4-pi-boost-deboost-setsched.tst+0−178
@@ -1,178 +0,0 @@
1−#
2−# rt-mutex test
3−#
4−# Op: C(ommand)/T(est)/W(ait)
5−# | opcode
6−# | | threadid: 0-7
7−# | | | opcode argument
8−# | | | |
9−# C: lock: 0: 0
10−#
11−# Commands
12−#
13−# opcode opcode argument
14−# schedother nice value
15−# schedfifo priority
16−# lock lock nr (0-7)
17−# locknowait lock nr (0-7)
18−# lockint lock nr (0-7)
19−# lockintnowait lock nr (0-7)
20−# lockcont lock nr (0-7)
21−# unlock lock nr (0-7)
22−# signal thread to signal (0-7)
23−# reset 0
24−# resetevent 0
25−#
26−# Tests / Wait
27−#
28−# opcode opcode argument
29−#
30−# prioeq priority
31−# priolt priority
32−# priogt priority
33−# nprioeq normal priority
34−# npriolt normal priority
35−# npriogt normal priority
36−# locked lock nr (0-7)
37−# blocked lock nr (0-7)
38−# blockedwake lock nr (0-7)
39−# unlocked lock nr (0-7)
40−# opcodeeq command opcode or number
41−# opcodelt number
42−# opcodegt number
43−# eventeq number
44−# eventgt number
45−# eventlt number
46−
47−#
48−# 5 threads 4 lock PI - modify priority of blocked threads
49−#
50−C: resetevent: 0: 0
51−W: opcodeeq: 0: 0
52−
53−# Set schedulers
54−C: schedother: 0: 0
55−C: schedfifo: 1: 81
56−C: schedfifo: 2: 82
57−C: schedfifo: 3: 83
58−C: schedfifo: 4: 84
59−
60−# T0 lock L0
61−C: locknowait: 0: 0
62−W: locked: 0: 0
63−
64−# T1 lock L1
65−C: locknowait: 1: 1
66−W: locked: 1: 1
67−
68−# T1 lock L0
69−C: lockintnowait: 1: 0
70−W: blocked: 1: 0
71−T: prioeq: 0: 81
72−
73−# T2 lock L2
74−C: locknowait: 2: 2
75−W: locked: 2: 2
76−
77−# T2 lock L1
78−C: lockintnowait: 2: 1
79−W: blocked: 2: 1
80−T: prioeq: 0: 82
81−T: prioeq: 1: 82
82−
83−# T3 lock L3
84−C: locknowait: 3: 3
85−W: locked: 3: 3
86−
87−# T3 lock L2
88−C: lockintnowait: 3: 2
89−W: blocked: 3: 2
90−T: prioeq: 0: 83
91−T: prioeq: 1: 83
92−T: prioeq: 2: 83
93−
94−# T4 lock L3
95−C: lockintnowait: 4: 3
96−W: blocked: 4: 3
97−T: prioeq: 0: 84
98−T: prioeq: 1: 84
99−T: prioeq: 2: 84
100−T: prioeq: 3: 84
101−
102−# Reduce prio of T4
103−C: schedfifo: 4: 80
104−T: prioeq: 0: 83
105−T: prioeq: 1: 83
106−T: prioeq: 2: 83
107−T: prioeq: 3: 83
108−T: prioeq: 4: 80
109−
110−# Increase prio of T4
111−C: schedfifo: 4: 84
112−T: prioeq: 0: 84
113−T: prioeq: 1: 84
114−T: prioeq: 2: 84
115−T: prioeq: 3: 84
116−T: prioeq: 4: 84
117−
118−# Reduce prio of T3
119−C: schedfifo: 3: 80
120−T: prioeq: 0: 84
121−T: prioeq: 1: 84
122−T: prioeq: 2: 84
123−T: prioeq: 3: 84
124−T: prioeq: 4: 84
125−
126−# Increase prio of T3
127−C: schedfifo: 3: 85
128−T: prioeq: 0: 85
129−T: prioeq: 1: 85
130−T: prioeq: 2: 85
131−T: prioeq: 3: 85
132−T: prioeq: 4: 84
133−
134−# Reduce prio of T3
135−C: schedfifo: 3: 83
136−T: prioeq: 0: 84
137−T: prioeq: 1: 84
138−T: prioeq: 2: 84
139−T: prioeq: 3: 84
140−T: prioeq: 4: 84
141−
142−# Signal T4
143−C: signal: 4: 0
144−W: unlocked: 4: 3
145−T: prioeq: 0: 83
146−T: prioeq: 1: 83
147−T: prioeq: 2: 83
148−T: prioeq: 3: 83
149−
150−# Signal T3
151−C: signal: 3: 0
152−W: unlocked: 3: 2
153−T: prioeq: 0: 82
154−T: prioeq: 1: 82
155−T: prioeq: 2: 82
156−
157−# Signal T2
158−C: signal: 2: 0
159−W: unlocked: 2: 1
160−T: prioeq: 0: 81
161−T: prioeq: 1: 81
162−
163−# Signal T1
164−C: signal: 1: 0
165−W: unlocked: 1: 0
166−T: priolt: 0: 1
167−
168−# Unlock and exit
169−C: unlock: 3: 3
170−C: unlock: 2: 2
171−C: unlock: 1: 1
172−C: unlock: 0: 0
173−
174−W: unlocked: 3: 3
175−W: unlocked: 2: 2
176−W: unlocked: 1: 1
177−W: unlocked: 0: 0
178−
scripts/rt-tester/t5-l4-pi-boost-deboost.tst+0−138
@@ -1,138 +0,0 @@
1−#
2−# rt-mutex test
3−#
4−# Op: C(ommand)/T(est)/W(ait)
5−# | opcode
6−# | | threadid: 0-7
7−# | | | opcode argument
8−# | | | |
9−# C: lock: 0: 0
10−#
11−# Commands
12−#
13−# opcode opcode argument
14−# schedother nice value
15−# schedfifo priority
16−# lock lock nr (0-7)
17−# locknowait lock nr (0-7)
18−# lockint lock nr (0-7)
19−# lockintnowait lock nr (0-7)
20−# lockcont lock nr (0-7)
21−# unlock lock nr (0-7)
22−# signal thread to signal (0-7)
23−# reset 0
24−# resetevent 0
25−#
26−# Tests / Wait
27−#
28−# opcode opcode argument
29−#
30−# prioeq priority
31−# priolt priority
32−# priogt priority
33−# nprioeq normal priority
34−# npriolt normal priority
35−# npriogt normal priority
36−# locked lock nr (0-7)
37−# blocked lock nr (0-7)
38−# blockedwake lock nr (0-7)
39−# unlocked lock nr (0-7)
40−# opcodeeq command opcode or number
41−# opcodelt number
42−# opcodegt number
43−# eventeq number
44−# eventgt number
45−# eventlt number
46−
47−#
48−# 5 threads 4 lock PI
49−#
50−C: resetevent: 0: 0
51−W: opcodeeq: 0: 0
52−
53−# Set schedulers
54−C: schedother: 0: 0
55−C: schedfifo: 1: 81
56−C: schedfifo: 2: 82
57−C: schedfifo: 3: 83
58−C: schedfifo: 4: 84
59−
60−# T0 lock L0
61−C: locknowait: 0: 0
62−W: locked: 0: 0
63−
64−# T1 lock L1
65−C: locknowait: 1: 1
66−W: locked: 1: 1
67−
68−# T1 lock L0
69−C: lockintnowait: 1: 0
70−W: blocked: 1: 0
71−T: prioeq: 0: 81
72−
73−# T2 lock L2
74−C: locknowait: 2: 2
75−W: locked: 2: 2
76−
77−# T2 lock L1
78−C: lockintnowait: 2: 1
79−W: blocked: 2: 1
80−T: prioeq: 0: 82
81−T: prioeq: 1: 82
82−
83−# T3 lock L3
84−C: locknowait: 3: 3
85−W: locked: 3: 3
86−
87−# T3 lock L2
88−C: lockintnowait: 3: 2
89−W: blocked: 3: 2
90−T: prioeq: 0: 83
91−T: prioeq: 1: 83
92−T: prioeq: 2: 83
93−
94−# T4 lock L3
95−C: lockintnowait: 4: 3
96−W: blocked: 4: 3
97−T: prioeq: 0: 84
98−T: prioeq: 1: 84
99−T: prioeq: 2: 84
100−T: prioeq: 3: 84
101−
102−# Signal T4
103−C: signal: 4: 0
104−W: unlocked: 4: 3
105−T: prioeq: 0: 83
106−T: prioeq: 1: 83
107−T: prioeq: 2: 83
108−T: prioeq: 3: 83
109−
110−# Signal T3
111−C: signal: 3: 0
112−W: unlocked: 3: 2
113−T: prioeq: 0: 82
114−T: prioeq: 1: 82
115−T: prioeq: 2: 82
116−
117−# Signal T2
118−C: signal: 2: 0
119−W: unlocked: 2: 1
120−T: prioeq: 0: 81
121−T: prioeq: 1: 81
122−
123−# Signal T1
124−C: signal: 1: 0
125−W: unlocked: 1: 0
126−T: priolt: 0: 1
127−
128−# Unlock and exit
129−C: unlock: 3: 3
130−C: unlock: 2: 2
131−C: unlock: 1: 1
132−C: unlock: 0: 0
133−
134−W: unlocked: 3: 3
135−W: unlocked: 2: 2
136−W: unlocked: 1: 1
137−W: unlocked: 0: 0
138−
tools/testing/selftests/Makefile+1−0
@@ -20,6 +20,7 @@ ifneq (1, $(quicktest)) · 19 unmodified lines
2020 TARGETS += timers
2121 endif
2222 TARGETS += user
23+TARGETS += jumplabel
2324 TARGETS += vm
2425 TARGETS += x86
2526 #Please keep the TARGETS list alphabetically sorted
tools/testing/selftests/static_keys/Makefile+8−0
@@ -0,0 +1,8 @@
1+# Makefile for static keys selftests
2+
3+# No binaries, but make sure arg-less "make" doesn't trigger "run_tests"
4+all:
5+
6+TEST_PROGS := test_static_keys.sh
7+
8+include ../lib.mk
tools/testing/selftests/static_keys/test_static_keys.sh+16−0
@@ -0,0 +1,16 @@
1+#!/bin/sh
2+# Runs static keys kernel module tests
3+
4+if /sbin/modprobe -q test_static_key_base; then
5+ if /sbin/modprobe -q test_static_keys; then
6+ echo "static_key: ok"
7+ /sbin/modprobe -q -r test_static_keys
8+ /sbin/modprobe -q -r test_static_key_base
9+ else
10+ echo "static_keys: [FAIL]"
11+ /sbin/modprobe -q -r test_static_key_base
12+ fi
13+else
14+ echo "static_key: [FAIL]"
15+ exit 1
16+fi