blob: 172a0cde59a268218186923eda4fe63bc243cb99 [file] [log] [blame]
Carl Shapiro93b0cb42010-06-03 17:05:15 -07001/*
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>
Carl Shapiro93b0cb42010-06-03 17:05:15 -070021
Ben Cheng5206d592012-12-07 10:54:09 -080022#ifndef ANDROID_ATOMIC_INLINE
23#define ANDROID_ATOMIC_INLINE inline __attribute__((always_inline))
24#endif
25
Ian Rogers62980e82013-01-31 16:40:21 -080026extern ANDROID_ATOMIC_INLINE void android_compiler_barrier()
Carl Shapiro93b0cb42010-06-03 17:05:15 -070027{
28 __asm__ __volatile__ ("" : : : "memory");
29}
30
Ian Rogers62980e82013-01-31 16:40:21 -080031extern ANDROID_ATOMIC_INLINE void android_memory_barrier()
32{
Carl Shapiro93b0cb42010-06-03 17:05:15 -070033#if ANDROID_SMP == 0
Brian Carlstrom464431e2010-09-24 10:56:43 -070034 android_compiler_barrier();
Carl Shapiro93b0cb42010-06-03 17:05:15 -070035#else
Ian Rogers62980e82013-01-31 16:40:21 -080036 __asm__ __volatile__ ("dmb" : : : "memory");
Carl Shapiro93b0cb42010-06-03 17:05:15 -070037#endif
Ian Rogers62980e82013-01-31 16:40:21 -080038}
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}
Carl Shapiro93b0cb42010-06-03 17:05:15 -070048
Ben Cheng5206d592012-12-07 10:54:09 -080049extern ANDROID_ATOMIC_INLINE
50int32_t android_atomic_acquire_load(volatile const int32_t *ptr)
Carl Shapiro93b0cb42010-06-03 17:05:15 -070051{
52 int32_t value = *ptr;
53 android_memory_barrier();
54 return value;
55}
56
Ben Cheng5206d592012-12-07 10:54:09 -080057extern ANDROID_ATOMIC_INLINE
58int32_t android_atomic_release_load(volatile const int32_t *ptr)
Carl Shapiro93b0cb42010-06-03 17:05:15 -070059{
60 android_memory_barrier();
61 return *ptr;
62}
63
Ian Rogers62980e82013-01-31 16:40:21 -080064extern ANDROID_ATOMIC_INLINE
65void android_atomic_acquire_store(int32_t value, volatile int32_t *ptr)
Carl Shapiro93b0cb42010-06-03 17:05:15 -070066{
67 *ptr = value;
68 android_memory_barrier();
69}
70
Ian Rogers62980e82013-01-31 16:40:21 -080071extern ANDROID_ATOMIC_INLINE
72void android_atomic_release_store(int32_t value, volatile int32_t *ptr)
Carl Shapiro93b0cb42010-06-03 17:05:15 -070073{
74 android_memory_barrier();
75 *ptr = value;
76}
77
Ian Rogers62980e82013-01-31 16:40:21 -080078extern ANDROID_ATOMIC_INLINE
79int android_atomic_cas(int32_t old_value, int32_t new_value,
80 volatile int32_t *ptr)
Carl Shapiro93b0cb42010-06-03 17:05:15 -070081{
82 int32_t prev, status;
83 do {
84 __asm__ __volatile__ ("ldrex %0, [%3]\n"
85 "mov %1, #0\n"
86 "teq %0, %4\n"
Ian Rogers62980e82013-01-31 16:40:21 -080087#ifdef __thumb2__
88 "it eq\n"
89#endif
Carl Shapiro93b0cb42010-06-03 17:05:15 -070090 "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}
Carl Shapiro93b0cb42010-06-03 17:05:15 -070097
Ian Rogers62980e82013-01-31 16:40:21 -080098extern ANDROID_ATOMIC_INLINE
99int android_atomic_acquire_cas(int32_t old_value, int32_t new_value,
100 volatile int32_t *ptr)
Carl Shapiro93b0cb42010-06-03 17:05:15 -0700101{
102 int status = android_atomic_cas(old_value, new_value, ptr);
103 android_memory_barrier();
104 return status;
105}
106
Ian Rogers62980e82013-01-31 16:40:21 -0800107extern ANDROID_ATOMIC_INLINE
108int android_atomic_release_cas(int32_t old_value, int32_t new_value,
109 volatile int32_t *ptr)
Carl Shapiro93b0cb42010-06-03 17:05:15 -0700110{
111 android_memory_barrier();
112 return android_atomic_cas(old_value, new_value, ptr);
113}
114
Ian Rogers62980e82013-01-31 16:40:21 -0800115extern ANDROID_ATOMIC_INLINE
116int32_t android_atomic_add(int32_t increment, volatile int32_t *ptr)
Carl Shapiro93b0cb42010-06-03 17:05:15 -0700117{
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}
Carl Shapiro93b0cb42010-06-03 17:05:15 -0700131
Ben Cheng5206d592012-12-07 10:54:09 -0800132extern ANDROID_ATOMIC_INLINE int32_t android_atomic_inc(volatile int32_t *addr)
Carl Shapirod55f0ad2010-09-28 13:47:03 -0700133{
Carl Shapiro93b0cb42010-06-03 17:05:15 -0700134 return android_atomic_add(1, addr);
135}
136
Ben Cheng5206d592012-12-07 10:54:09 -0800137extern ANDROID_ATOMIC_INLINE int32_t android_atomic_dec(volatile int32_t *addr)
Carl Shapirod55f0ad2010-09-28 13:47:03 -0700138{
Carl Shapiro93b0cb42010-06-03 17:05:15 -0700139 return android_atomic_add(-1, addr);
140}
141
Ian Rogers62980e82013-01-31 16:40:21 -0800142extern ANDROID_ATOMIC_INLINE
143int32_t android_atomic_and(int32_t value, volatile int32_t *ptr)
Carl Shapiro93b0cb42010-06-03 17:05:15 -0700144{
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}
Carl Shapiro93b0cb42010-06-03 17:05:15 -0700158
Ian Rogers62980e82013-01-31 16:40:21 -0800159extern ANDROID_ATOMIC_INLINE
160int32_t android_atomic_or(int32_t value, volatile int32_t *ptr)
Carl Shapiro93b0cb42010-06-03 17:05:15 -0700161{
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}
Carl Shapiro93b0cb42010-06-03 17:05:15 -0700175
176#endif /* ANDROID_CUTILS_ATOMIC_ARM_H */