• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Keine Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

Revisionfc48f4fb0506b2ea6ef3bb33037be3a4da2874bc (tree)
Zeit2020-08-11 20:35:02
AutorMax Filippov <jcmvbkbc@gmai...>
CommiterWaldemar Brodkorb

Log Message

xtensa: add exclusive access support

Add XCHAL definitions for S32C1I and EXCLUSIVE options to
xtensa-config.h, include it in places that implement atomic operations
and add implementations with exclusive access option opcodes.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>

Ändern Zusammenfassung

Diff

--- a/libc/sysdeps/linux/xtensa/bits/atomic.h
+++ b/libc/sysdeps/linux/xtensa/bits/atomic.h
@@ -18,6 +18,7 @@
1818 #ifndef _BITS_ATOMIC_H
1919 #define _BITS_ATOMIC_H 1
2020
21+#include <bits/xtensa-config.h>
2122 #include <inttypes.h>
2223
2324 typedef int32_t atomic32_t;
@@ -50,6 +51,128 @@ typedef uintmax_t uatomic_max_t;
5051 #define __arch_compare_and_exchange_bool_16_rel(mem, newval, oldval) \
5152 (abort (), 0)
5253
54+#if XCHAL_HAVE_EXCLUSIVE
55+
56+/* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
57+ Return the old *MEM value. */
58+
59+#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
60+ ({__typeof__(*(mem)) __tmp, __value; \
61+ __asm__ __volatile__( \
62+ " memw \n" \
63+ "1: l32ex %0, %2 \n" \
64+ " bne %0, %4, 2f \n" \
65+ " mov %1, %3 \n" \
66+ " s32ex %1, %2 \n" \
67+ " getex %1 \n" \
68+ " beqz %1, 1b \n" \
69+ " memw \n" \
70+ "2: \n" \
71+ : "=&a" (__value), "=&a" (__tmp) \
72+ : "a" (mem), "a" (newval), "a" (oldval) \
73+ : "memory" ); \
74+ __value; \
75+ })
76+
77+/* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
78+ Return zero if *MEM was changed or non-zero if no exchange happened. */
79+
80+#define __arch_compare_and_exchange_bool_32_acq(mem, newval, oldval) \
81+ ({__typeof__(*(mem)) __tmp, __value; \
82+ __asm__ __volatile__( \
83+ " memw \n" \
84+ "1: l32ex %0, %2 \n" \
85+ " sub %0, %4, %0 \n" \
86+ " bnez %0, 2f \n" \
87+ " mov %1, %3 \n" \
88+ " s32ex %1, %2 \n" \
89+ " getex %1 \n" \
90+ " beqz %1, 1b \n" \
91+ " movi %0, 0 \n" \
92+ " memw \n" \
93+ "2: \n" \
94+ : "=&a" (__value), "=&a" (__tmp) \
95+ : "a" (mem), "a" (newval), "a" (oldval) \
96+ : "memory" ); \
97+ __value != 0; \
98+ })
99+
100+/* Store NEWVALUE in *MEM and return the old value. */
101+
102+#define __arch_exchange_32_acq(mem, newval) \
103+ ({__typeof__(*(mem)) __tmp, __value; \
104+ __asm__ __volatile__( \
105+ " memw \n" \
106+ "1: l32ex %0, %2 \n" \
107+ " mov %1, %3 \n" \
108+ " s32ex %1, %2 \n" \
109+ " getex %1 \n" \
110+ " beqz %1, 1b \n" \
111+ " memw \n" \
112+ : "=&a" (__value), "=&a" (__tmp) \
113+ : "a" (mem), "a" (newval) \
114+ : "memory" ); \
115+ __value; \
116+ })
117+
118+/* Add VALUE to *MEM and return the old value of *MEM. */
119+
120+#define __arch_atomic_exchange_and_add_32(mem, value) \
121+ ({__typeof__(*(mem)) __tmp, __value; \
122+ __asm__ __volatile__( \
123+ " memw \n" \
124+ "1: l32ex %0, %2 \n" \
125+ " add %1, %0, %3 \n" \
126+ " s32ex %1, %2 \n" \
127+ " getex %1 \n" \
128+ " beqz %1, 1b \n" \
129+ " memw \n" \
130+ : "=&a" (__value), "=&a" (__tmp) \
131+ : "a" (mem), "a" (value) \
132+ : "memory" ); \
133+ __value; \
134+ })
135+
136+/* Subtract VALUE from *MEM and return the old value of *MEM. */
137+
138+#define __arch_atomic_exchange_and_sub_32(mem, value) \
139+ ({__typeof__(*(mem)) __tmp, __value; \
140+ __asm__ __volatile__( \
141+ " memw \n" \
142+ "1: l32ex %0, %2 \n" \
143+ " sub %1, %0, %3 \n" \
144+ " s32ex %1, %2 \n" \
145+ " getex %1 \n" \
146+ " beqz %1, 1b \n" \
147+ " memw \n" \
148+ : "=&a" (__value), "=&a" (__tmp) \
149+ : "a" (mem), "a" (value) \
150+ : "memory" ); \
151+ __tmp; \
152+ })
153+
154+/* Decrement *MEM if it is > 0, and return the old value. */
155+
156+#define __arch_atomic_decrement_if_positive_32(mem) \
157+ ({__typeof__(*(mem)) __tmp, __value; \
158+ __asm__ __volatile__( \
159+ " memw \n" \
160+ "1: l32ex %0, %2 \n" \
161+ " blti %0, 1, 2f \n" \
162+ " addi %1, %0, -1 \n" \
163+ " s32ex %1, %2 \n" \
164+ " getex %1 \n" \
165+ " beqz %1, 1b \n" \
166+ " memw \n" \
167+ "2: \n" \
168+ : "=&a" (__value), "=&a" (__tmp) \
169+ : "a" (mem) \
170+ : "memory" ); \
171+ __value; \
172+ })
173+
174+#elif XCHAL_HAVE_S32C1I
175+
53176 /* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL.
54177 Return the old *MEM value. */
55178
@@ -156,6 +279,11 @@ typedef uintmax_t uatomic_max_t;
156279 __value; \
157280 })
158281
282+#else
283+
284+#error No hardware atomic operations
285+
286+#endif
159287
160288 /* These are the preferred public interfaces: */
161289
--- a/libc/sysdeps/linux/xtensa/bits/xtensa-config.h
+++ b/libc/sysdeps/linux/xtensa/bits/xtensa-config.h
@@ -43,4 +43,10 @@
4343 #undef XCHAL_NUM_AREGS
4444 #define XCHAL_NUM_AREGS 64
4545
46+#undef XCHAL_HAVE_S32C1I
47+#define XCHAL_HAVE_S32C1I 1
48+
49+#undef XCHAL_HAVE_EXCLUSIVE
50+#define XCHAL_HAVE_EXCLUSIVE 0
51+
4652 #endif /* !XTENSA_CONFIG_H */
--- a/libpthread/linuxthreads/sysdeps/xtensa/pt-machine.h
+++ b/libpthread/linuxthreads/sysdeps/xtensa/pt-machine.h
@@ -21,6 +21,7 @@
2121 #ifndef _PT_MACHINE_H
2222 #define _PT_MACHINE_H 1
2323
24+#include <bits/xtensa-config.h>
2425 #include <sys/syscall.h>
2526 #include <asm/unistd.h>
2627
@@ -34,6 +35,55 @@
3435 extern long int testandset (int *spinlock);
3536 extern int __compare_and_swap (long int *p, long int oldval, long int newval);
3637
38+#if XCHAL_HAVE_EXCLUSIVE
39+
40+/* Spinlock implementation; required. */
41+PT_EI long int
42+testandset (int *spinlock)
43+{
44+ unsigned long tmp;
45+ __asm__ volatile (
46+" memw \n"
47+"1: l32ex %0, %1 \n"
48+" bnez %0, 2f \n"
49+" movi %0, 1 \n"
50+" s32ex %0, %1 \n"
51+" getex %0 \n"
52+" beqz %0, 1b \n"
53+" movi %0, 0 \n"
54+" memw \n"
55+"2: \n"
56+ : "=&a" (tmp)
57+ : "a" (spinlock)
58+ : "memory"
59+ );
60+ return tmp;
61+}
62+
63+PT_EI int
64+__compare_and_swap (long int *p, long int oldval, long int newval)
65+{
66+ unsigned long tmp;
67+ unsigned long value;
68+ __asm__ volatile (
69+" memw \n"
70+"1: l32ex %0, %2 \n"
71+" bne %0, %4, 2f \n"
72+" mov %1, %3 \n"
73+" s32ex %1, %2 \n"
74+" getex %1 \n"
75+" beqz %1, 1b \n"
76+" memw \n"
77+"2: \n"
78+ : "=&a" (tmp), "=&a" (value)
79+ : "a" (p), "a" (newval), "a" (oldval)
80+ : "memory" );
81+
82+ return tmp == oldval;
83+}
84+
85+#elif XCHAL_HAVE_S32C1I
86+
3787 /* Spinlock implementation; required. */
3888 PT_EI long int
3989 testandset (int *spinlock)
@@ -71,6 +121,12 @@ __compare_and_swap (long int *p, long int oldval, long int newval)
71121 return tmp == oldval;
72122 }
73123
124+#else
125+
126+#error No hardware atomic operations
127+
128+#endif
129+
74130 /* Get some notion of the current stack. Need not be exactly the top
75131 of the stack, just something somewhere in the current frame. */
76132 #define CURRENT_STACK_FRAME __builtin_frame_address (0)
--- a/libpthread/nptl/sysdeps/xtensa/pthread_spin_lock.S
+++ b/libpthread/nptl/sysdeps/xtensa/pthread_spin_lock.S
@@ -15,16 +15,32 @@
1515 License along with the GNU C Library; see the file COPYING.LIB. If
1616 not, see <http://www.gnu.org/licenses/>.  */
1717
18+#include <bits/xtensa-config.h>
1819 #include <sysdep.h>
1920
2021 .text
2122 ENTRY (pthread_spin_lock)
2223
24+#if XCHAL_HAVE_EXCLUSIVE
25+ memw
26+1: l32ex a3, a2
27+ bnez a3, 1b
28+ movi a3, 1
29+ s32ex a3, a2
30+ getex a3
31+ beqz a3, 1b
32+ memw
33+#elif XCHAL_HAVE_S32C1I
2334 movi a3, 0
2435 wsr a3, scompare1
2536 movi a3, 1
2637 1: s32c1i a3, a2, 0
2738 bnez a3, 1b
39+#else
40+
41+#error No hardware atomic operations
42+
43+#endif
2844 movi a2, 0
2945
3046 abi_ret
--- a/libpthread/nptl/sysdeps/xtensa/pthread_spin_trylock.S
+++ b/libpthread/nptl/sysdeps/xtensa/pthread_spin_trylock.S
@@ -17,15 +17,32 @@
1717
1818 #define _ERRNO_H 1
1919 #include <bits/errno.h>
20+#include <bits/xtensa-config.h>
2021 #include <sysdep.h>
2122
2223 .text
2324 ENTRY (pthread_spin_trylock)
2425
26+#if XCHAL_HAVE_EXCLUSIVE
27+ memw
28+ l32ex a3, a2
29+ bnez a3, 1f
30+ movi a3, 1
31+ s32ex a3, a2
32+ getex a3
33+ addi a3, a3, -1
34+ memw
35+1:
36+#elif XCHAL_HAVE_S32C1I
2537 movi a3, 0
2638 wsr a3, scompare1
2739 movi a3, 1
2840 s32c1i a3, a2, 0
41+#else
42+
43+#error No hardware atomic operations
44+
45+#endif
2946 movi a2, EBUSY
3047 moveqz a2, a3, a3
3148