111
|
1 /* Copyright (C) 2012-2017 Free Software Foundation, Inc.
|
|
2 Contributed by Richard Henderson <rth@redhat.com>.
|
|
3
|
|
4 This file is part of the GNU Atomic Library (libatomic).
|
|
5
|
|
6 Libatomic is free software; you can redistribute it and/or modify it
|
|
7 under the terms of the GNU General Public License as published by
|
|
8 the Free Software Foundation; either version 3 of the License, or
|
|
9 (at your option) any later version.
|
|
10
|
|
11 Libatomic is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
13 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
14 more details.
|
|
15
|
|
16 Under Section 7 of GPL version 3, you are granted additional
|
|
17 permissions described in the GCC Runtime Library Exception, version
|
|
18 3.1, as published by the Free Software Foundation.
|
|
19
|
|
20 You should have received a copy of the GNU General Public License and
|
|
21 a copy of the GCC Runtime Library Exception along with this program;
|
|
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
|
23 <http://www.gnu.org/licenses/>. */
|
|
24
|
|
25 #include <config/arm/arm-config.h>
|
|
26
|
|
27
|
|
28 /* Kernel helper for 32-bit compare-and-exchange. */
|
|
29 typedef int (__kernel_cmpxchg_t) (UWORD oldval, UWORD newval, UWORD *ptr);
|
|
30 #define __kernel_cmpxchg (*(__kernel_cmpxchg_t *) 0xffff0fc0)
|
|
31
|
|
32 /* Kernel helper for 64-bit compare-and-exchange. */
|
|
33 typedef int (__kernel_cmpxchg64_t) (const U_8 * oldval, const U_8 * newval,
|
|
34 U_8 *ptr);
|
|
35 #define __kernel_cmpxchg64 (*(__kernel_cmpxchg64_t *) 0xffff0f60)
|
|
36
|
|
37 /* Kernel helper for memory barrier. */
|
|
38 typedef void (__kernel_dmb_t) (void);
|
|
39 #define __kernel_dmb (*(__kernel_dmb_t *) 0xffff0fa0)
|
|
40
|
|
41 /* Kernel helper page version number. */
|
|
42 #define __kernel_helper_version (*(unsigned int *)0xffff0ffc)
|
|
43
|
|
44
|
|
45 #ifndef HAVE_STREX
|
|
46 static inline bool
|
|
47 atomic_compare_exchange_w (UWORD *mptr, UWORD *eptr, UWORD newval,
|
|
48 bool weak_p UNUSED, int sm UNUSED, int fm UNUSED)
|
|
49 {
|
|
50 bool ret = true;
|
|
51 UWORD oldval;
|
|
52
|
|
53 oldval = *eptr;
|
|
54 if (__builtin_expect (__kernel_cmpxchg (oldval, newval, mptr) != 0, 0))
|
|
55 {
|
|
56 oldval = *mptr;
|
|
57 ret = false;
|
|
58 }
|
|
59 *eptr = oldval;
|
|
60
|
|
61 return ret;
|
|
62 }
|
|
63 # define atomic_compare_exchange_w atomic_compare_exchange_w
|
|
64 # if N == WORDSIZE
|
|
65 # define atomic_compare_exchange_n atomic_compare_exchange_w
|
|
66 # endif
|
|
67 #endif /* HAVE_STREX */
|
|
68
|
|
69 #if !defined(HAVE_STREXBHD) && defined(HAVE_KERNEL64) && N == 8
|
|
70 static inline bool
|
|
71 atomic_compare_exchange_n (UTYPE *mptr, UTYPE *eptr, UTYPE newval,
|
|
72 bool weak_p UNUSED, int sm UNUSED, int fm UNUSED)
|
|
73 {
|
|
74 if (__kernel_cmpxchg64 (eptr, &newval, mptr) == 0)
|
|
75 return true;
|
|
76 else
|
|
77 {
|
|
78 *eptr = *mptr;
|
|
79 return false;
|
|
80 }
|
|
81 }
|
|
82 #define atomic_compare_exchange_n atomic_compare_exchange_n
|
|
83 #endif
|
|
84
|
|
85 #if !defined(HAVE_DMB) && !defined(HAVE_DMB_MCR)
|
|
86 static inline void
|
|
87 pre_barrier(int model UNUSED)
|
|
88 {
|
|
89 __kernel_dmb ();
|
|
90 }
|
|
91
|
|
92 static inline void
|
|
93 post_barrier(int model UNUSED)
|
|
94 {
|
|
95 __kernel_dmb ();
|
|
96 }
|
|
97 # define pre_post_barrier 1
|
|
98 #endif /* !HAVE_DMB */
|
|
99
|
|
100 #if HAVE_IFUNC
|
|
101 extern bool libat_have_strexbhd HIDDEN;
|
|
102
|
|
103 # define IFUNC_COND_1 libat_have_strexbhd
|
|
104 # define IFUNC_COND_2 (__kernel_helper_version >= 5)
|
|
105
|
|
106 /* Alternative 1 is -march=armv7-a -- we have everything native. */
|
|
107 # if IFUNC_ALT == 1
|
|
108 # undef HAVE_ATOMIC_CAS_1
|
|
109 # undef HAVE_ATOMIC_CAS_2
|
|
110 # undef HAVE_ATOMIC_CAS_4
|
|
111 # undef HAVE_ATOMIC_CAS_8
|
|
112 # undef HAVE_ATOMIC_EXCHANGE_1
|
|
113 # undef HAVE_ATOMIC_EXCHANGE_2
|
|
114 # undef HAVE_ATOMIC_EXCHANGE_4
|
|
115 # undef HAVE_ATOMIC_EXCHANGE_8
|
|
116 # undef HAVE_ATOMIC_LDST_1
|
|
117 # undef HAVE_ATOMIC_LDST_2
|
|
118 # undef HAVE_ATOMIC_LDST_4
|
|
119 # undef HAVE_ATOMIC_LDST_8
|
|
120 # undef HAVE_ATOMIC_FETCH_OP_1
|
|
121 # undef HAVE_ATOMIC_FETCH_OP_2
|
|
122 # undef HAVE_ATOMIC_FETCH_OP_4
|
|
123 # undef HAVE_ATOMIC_FETCH_OP_8
|
|
124 # undef HAVE_ATOMIC_TAS_1
|
|
125 # undef HAVE_ATOMIC_TAS_2
|
|
126 # undef HAVE_ATOMIC_TAS_4
|
|
127 # undef HAVE_ATOMIC_TAS_8
|
|
128 # define HAVE_ATOMIC_CAS_1 1
|
|
129 # define HAVE_ATOMIC_CAS_2 1
|
|
130 # define HAVE_ATOMIC_CAS_4 1
|
|
131 # define HAVE_ATOMIC_CAS_8 1
|
|
132 # define HAVE_ATOMIC_EXCHANGE_1 1
|
|
133 # define HAVE_ATOMIC_EXCHANGE_2 1
|
|
134 # define HAVE_ATOMIC_EXCHANGE_4 1
|
|
135 # define HAVE_ATOMIC_EXCHANGE_8 1
|
|
136 # define HAVE_ATOMIC_LDST_1 1
|
|
137 # define HAVE_ATOMIC_LDST_2 1
|
|
138 # define HAVE_ATOMIC_LDST_4 1
|
|
139 # define HAVE_ATOMIC_LDST_8 1
|
|
140 # define HAVE_ATOMIC_FETCH_OP_1 1
|
|
141 # define HAVE_ATOMIC_FETCH_OP_2 1
|
|
142 # define HAVE_ATOMIC_FETCH_OP_4 1
|
|
143 # define HAVE_ATOMIC_FETCH_OP_8 1
|
|
144 # define HAVE_ATOMIC_TAS_1 1
|
|
145 # define HAVE_ATOMIC_TAS_2 1
|
|
146 # define HAVE_ATOMIC_TAS_4 1
|
|
147 # define HAVE_ATOMIC_TAS_8 1
|
|
148 # endif /* IFUNC_ALT == 1 */
|
|
149
|
|
150 # undef MAYBE_HAVE_ATOMIC_CAS_1
|
|
151 # define MAYBE_HAVE_ATOMIC_CAS_1 IFUNC_COND_1
|
|
152 # undef MAYBE_HAVE_ATOMIC_EXCHANGE_1
|
|
153 # define MAYBE_HAVE_ATOMIC_EXCHANGE_1 MAYBE_HAVE_ATOMIC_CAS_1
|
|
154 # undef MAYBE_HAVE_ATOMIC_LDST_1
|
|
155 # define MAYBE_HAVE_ATOMIC_LDST_1 MAYBE_HAVE_ATOMIC_CAS_1
|
|
156 # undef MAYBE_HAVE_ATOMIC_CAS_2
|
|
157 # define MAYBE_HAVE_ATOMIC_CAS_2 IFUNC_COND_1
|
|
158 # undef MAYBE_HAVE_ATOMIC_EXCHANGE_2
|
|
159 # define MAYBE_HAVE_ATOMIC_EXCHANGE_2 MAYBE_HAVE_ATOMIC_CAS_2
|
|
160 # undef MAYBE_HAVE_ATOMIC_LDST_2
|
|
161 # define MAYBE_HAVE_ATOMIC_LDST_2 MAYBE_HAVE_ATOMIC_CAS_2
|
|
162 # undef MAYBE_HAVE_ATOMIC_CAS_4
|
|
163 # define MAYBE_HAVE_ATOMIC_CAS_4 IFUNC_COND_1
|
|
164 # undef MAYBE_HAVE_ATOMIC_EXCHANGE_4
|
|
165 # define MAYBE_HAVE_ATOMIC_EXCHANGE_4 MAYBE_HAVE_ATOMIC_CAS_4
|
|
166 # undef MAYBE_HAVE_ATOMIC_LDST_4
|
|
167 # define MAYBE_HAVE_ATOMIC_LDST_4 MAYBE_HAVE_ATOMIC_CAS_4
|
|
168 # undef MAYBE_HAVE_ATOMIC_CAS_8
|
|
169 # define MAYBE_HAVE_ATOMIC_CAS_8 (IFUNC_COND_1 | IFUNC_COND_2)
|
|
170 # undef MAYBE_HAVE_ATOMIC_EXCHANGE_8
|
|
171 # define MAYBE_HAVE_ATOMIC_EXCHANGE_8 MAYBE_HAVE_ATOMIC_CAS_8
|
|
172 # undef MAYBE_HAVE_ATOMIC_LDST_8
|
|
173 # define MAYBE_HAVE_ATOMIC_LDST_8 MAYBE_HAVE_ATOMIC_CAS_8
|
|
174
|
|
175 # define IFUNC_NCOND(N) (N == 8 ? 2 : 1)
|
|
176
|
|
177 #endif /* HAVE_IFUNC */
|
|
178
|
|
179 #include_next <host-config.h>
|