blob: 172a0cde59a268218186923eda4fe63bc243cb99 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ANDROID_CUTILS_ATOMIC_ARM_H
18#define ANDROID_CUTILS_ATOMIC_ARM_H
19
20#include <stdint.h>
21
22#ifndef ANDROID_ATOMIC_INLINE
23#define ANDROID_ATOMIC_INLINE inline __attribute__((always_inline))
24#endif
25
26extern ANDROID_ATOMIC_INLINE void android_compiler_barrier()
27{
28 __asm__ __volatile__ ("" : : : "memory");
29}
30
31extern ANDROID_ATOMIC_INLINE void android_memory_barrier()
32{
33#if ANDROID_SMP == 0
34 android_compiler_barrier();
35#else
36 __asm__ __volatile__ ("dmb" : : : "memory");
37#endif
38}
39
40extern ANDROID_ATOMIC_INLINE void android_memory_store_barrier()
41{
42#if ANDROID_SMP == 0
43 android_compiler_barrier();
44#else
45 __asm__ __volatile__ ("dmb st" : : : "memory");
46#endif
47}
48
49extern ANDROID_ATOMIC_INLINE
50int32_t android_atomic_acquire_load(volatile const int32_t *ptr)
51{
52 int32_t value = *ptr;
53 android_memory_barrier();
54 return value;
55}
56
57extern ANDROID_ATOMIC_INLINE
58int32_t android_atomic_release_load(volatile const int32_t *ptr)
59{
60 android_memory_barrier();
61 return *ptr;
62}
63
64extern ANDROID_ATOMIC_INLINE
65void android_atomic_acquire_store(int32_t value, volatile int32_t *ptr)
66{
67 *ptr = value;
68 android_memory_barrier();
69}
70
71extern ANDROID_ATOMIC_INLINE
72void android_atomic_release_store(int32_t value, volatile int32_t *ptr)
73{
74 android_memory_barrier();
75 *ptr = value;
76}
77
78extern ANDROID_ATOMIC_INLINE
79int android_atomic_cas(int32_t old_value, int32_t new_value,
80 volatile int32_t *ptr)
81{
82 int32_t prev, status;
83 do {
84 __asm__ __volatile__ ("ldrex %0, [%3]\n"
85 "mov %1, #0\n"
86 "teq %0, %4\n"
87#ifdef __thumb2__
88 "it eq\n"
89#endif
90 "strexeq %1, %5, [%3]"
91 : "=&r" (prev), "=&r" (status), "+m"(*ptr)
92 : "r" (ptr), "Ir" (old_value), "r" (new_value)
93 : "cc");
94 } while (__builtin_expect(status != 0, 0));
95 return prev != old_value;
96}
97
98extern ANDROID_ATOMIC_INLINE
99int android_atomic_acquire_cas(int32_t old_value, int32_t new_value,
100 volatile int32_t *ptr)
101{
102 int status = android_atomic_cas(old_value, new_value, ptr);
103 android_memory_barrier();
104 return status;
105}
106
107extern ANDROID_ATOMIC_INLINE
108int android_atomic_release_cas(int32_t old_value, int32_t new_value,
109 volatile int32_t *ptr)
110{
111 android_memory_barrier();
112 return android_atomic_cas(old_value, new_value, ptr);
113}
114
115extern ANDROID_ATOMIC_INLINE
116int32_t android_atomic_add(int32_t increment, volatile int32_t *ptr)
117{
118 int32_t prev, tmp, status;
119 android_memory_barrier();
120 do {
121 __asm__ __volatile__ ("ldrex %0, [%4]\n"
122 "add %1, %0, %5\n"
123 "strex %2, %1, [%4]"
124 : "=&r" (prev), "=&r" (tmp),
125 "=&r" (status), "+m" (*ptr)
126 : "r" (ptr), "Ir" (increment)
127 : "cc");
128 } while (__builtin_expect(status != 0, 0));
129 return prev;
130}
131
132extern ANDROID_ATOMIC_INLINE int32_t android_atomic_inc(volatile int32_t *addr)
133{
134 return android_atomic_add(1, addr);
135}
136
137extern ANDROID_ATOMIC_INLINE int32_t android_atomic_dec(volatile int32_t *addr)
138{
139 return android_atomic_add(-1, addr);
140}
141
142extern ANDROID_ATOMIC_INLINE
143int32_t android_atomic_and(int32_t value, volatile int32_t *ptr)
144{
145 int32_t prev, tmp, status;
146 android_memory_barrier();
147 do {
148 __asm__ __volatile__ ("ldrex %0, [%4]\n"
149 "and %1, %0, %5\n"
150 "strex %2, %1, [%4]"
151 : "=&r" (prev), "=&r" (tmp),
152 "=&r" (status), "+m" (*ptr)
153 : "r" (ptr), "Ir" (value)
154 : "cc");
155 } while (__builtin_expect(status != 0, 0));
156 return prev;
157}
158
159extern ANDROID_ATOMIC_INLINE
160int32_t android_atomic_or(int32_t value, volatile int32_t *ptr)
161{
162 int32_t prev, tmp, status;
163 android_memory_barrier();
164 do {
165 __asm__ __volatile__ ("ldrex %0, [%4]\n"
166 "orr %1, %0, %5\n"
167 "strex %2, %1, [%4]"
168 : "=&r" (prev), "=&r" (tmp),
169 "=&r" (status), "+m" (*ptr)
170 : "r" (ptr), "Ir" (value)
171 : "cc");
172 } while (__builtin_expect(status != 0, 0));
173 return prev;
174}
175
176#endif /* ANDROID_CUTILS_ATOMIC_ARM_H */