blob: 6b031b678623ac6ee929cc506749e846663ef9e5 [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
Ben Cheng5206d592012-12-07 10:54:09 -080040extern ANDROID_ATOMIC_INLINE
41int32_t android_atomic_acquire_load(volatile const int32_t *ptr)
Carl Shapiro93b0cb42010-06-03 17:05:15 -070042{
43 int32_t value = *ptr;
44 android_memory_barrier();
45 return value;
46}
47
Ben Cheng5206d592012-12-07 10:54:09 -080048extern ANDROID_ATOMIC_INLINE
49int32_t android_atomic_release_load(volatile const int32_t *ptr)
Carl Shapiro93b0cb42010-06-03 17:05:15 -070050{
51 android_memory_barrier();
52 return *ptr;
53}
54
Ian Rogers62980e82013-01-31 16:40:21 -080055extern ANDROID_ATOMIC_INLINE
56void android_atomic_acquire_store(int32_t value, volatile int32_t *ptr)
Carl Shapiro93b0cb42010-06-03 17:05:15 -070057{
58 *ptr = value;
59 android_memory_barrier();
60}
61
Ian Rogers62980e82013-01-31 16:40:21 -080062extern ANDROID_ATOMIC_INLINE
63void android_atomic_release_store(int32_t value, volatile int32_t *ptr)
Carl Shapiro93b0cb42010-06-03 17:05:15 -070064{
65 android_memory_barrier();
66 *ptr = value;
67}
68
Ian Rogers62980e82013-01-31 16:40:21 -080069extern ANDROID_ATOMIC_INLINE
70int android_atomic_cas(int32_t old_value, int32_t new_value,
71 volatile int32_t *ptr)
Carl Shapiro93b0cb42010-06-03 17:05:15 -070072{
73 int32_t prev, status;
74 do {
75 __asm__ __volatile__ ("ldrex %0, [%3]\n"
76 "mov %1, #0\n"
77 "teq %0, %4\n"
Ian Rogers62980e82013-01-31 16:40:21 -080078#ifdef __thumb2__
79 "it eq\n"
80#endif
Carl Shapiro93b0cb42010-06-03 17:05:15 -070081 "strexeq %1, %5, [%3]"
82 : "=&r" (prev), "=&r" (status), "+m"(*ptr)
83 : "r" (ptr), "Ir" (old_value), "r" (new_value)
84 : "cc");
85 } while (__builtin_expect(status != 0, 0));
86 return prev != old_value;
87}
Carl Shapiro93b0cb42010-06-03 17:05:15 -070088
Ian Rogers62980e82013-01-31 16:40:21 -080089extern ANDROID_ATOMIC_INLINE
90int android_atomic_acquire_cas(int32_t old_value, int32_t new_value,
91 volatile int32_t *ptr)
Carl Shapiro93b0cb42010-06-03 17:05:15 -070092{
93 int status = android_atomic_cas(old_value, new_value, ptr);
94 android_memory_barrier();
95 return status;
96}
97
Ian Rogers62980e82013-01-31 16:40:21 -080098extern ANDROID_ATOMIC_INLINE
99int android_atomic_release_cas(int32_t old_value, int32_t new_value,
100 volatile int32_t *ptr)
Carl Shapiro93b0cb42010-06-03 17:05:15 -0700101{
102 android_memory_barrier();
103 return android_atomic_cas(old_value, new_value, ptr);
104}
105
Ian Rogers62980e82013-01-31 16:40:21 -0800106extern ANDROID_ATOMIC_INLINE
107int32_t android_atomic_add(int32_t increment, volatile int32_t *ptr)
Carl Shapiro93b0cb42010-06-03 17:05:15 -0700108{
109 int32_t prev, tmp, status;
110 android_memory_barrier();
111 do {
112 __asm__ __volatile__ ("ldrex %0, [%4]\n"
113 "add %1, %0, %5\n"
114 "strex %2, %1, [%4]"
115 : "=&r" (prev), "=&r" (tmp),
116 "=&r" (status), "+m" (*ptr)
117 : "r" (ptr), "Ir" (increment)
118 : "cc");
119 } while (__builtin_expect(status != 0, 0));
120 return prev;
121}
Carl Shapiro93b0cb42010-06-03 17:05:15 -0700122
Ben Cheng5206d592012-12-07 10:54:09 -0800123extern ANDROID_ATOMIC_INLINE int32_t android_atomic_inc(volatile int32_t *addr)
Carl Shapirod55f0ad2010-09-28 13:47:03 -0700124{
Carl Shapiro93b0cb42010-06-03 17:05:15 -0700125 return android_atomic_add(1, addr);
126}
127
Ben Cheng5206d592012-12-07 10:54:09 -0800128extern ANDROID_ATOMIC_INLINE int32_t android_atomic_dec(volatile int32_t *addr)
Carl Shapirod55f0ad2010-09-28 13:47:03 -0700129{
Carl Shapiro93b0cb42010-06-03 17:05:15 -0700130 return android_atomic_add(-1, addr);
131}
132
Ian Rogers62980e82013-01-31 16:40:21 -0800133extern ANDROID_ATOMIC_INLINE
134int32_t android_atomic_and(int32_t value, volatile int32_t *ptr)
Carl Shapiro93b0cb42010-06-03 17:05:15 -0700135{
136 int32_t prev, tmp, status;
137 android_memory_barrier();
138 do {
139 __asm__ __volatile__ ("ldrex %0, [%4]\n"
140 "and %1, %0, %5\n"
141 "strex %2, %1, [%4]"
142 : "=&r" (prev), "=&r" (tmp),
143 "=&r" (status), "+m" (*ptr)
144 : "r" (ptr), "Ir" (value)
145 : "cc");
146 } while (__builtin_expect(status != 0, 0));
147 return prev;
148}
Carl Shapiro93b0cb42010-06-03 17:05:15 -0700149
Ian Rogers62980e82013-01-31 16:40:21 -0800150extern ANDROID_ATOMIC_INLINE
151int32_t android_atomic_or(int32_t value, volatile int32_t *ptr)
Carl Shapiro93b0cb42010-06-03 17:05:15 -0700152{
153 int32_t prev, tmp, status;
154 android_memory_barrier();
155 do {
156 __asm__ __volatile__ ("ldrex %0, [%4]\n"
157 "orr %1, %0, %5\n"
158 "strex %2, %1, [%4]"
159 : "=&r" (prev), "=&r" (tmp),
160 "=&r" (status), "+m" (*ptr)
161 : "r" (ptr), "Ir" (value)
162 : "cc");
163 } while (__builtin_expect(status != 0, 0));
164 return prev;
165}
Carl Shapiro93b0cb42010-06-03 17:05:15 -0700166
167#endif /* ANDROID_CUTILS_ATOMIC_ARM_H */