• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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_X86_H
18 #define ANDROID_CUTILS_ATOMIC_X86_H
19 
20 #include <stdint.h>
21 
android_compiler_barrier(void)22 extern inline void android_compiler_barrier(void)
23 {
24     __asm__ __volatile__ ("" : : : "memory");
25 }
26 
27 #if ANDROID_SMP == 0
android_memory_barrier(void)28 extern inline void android_memory_barrier(void)
29 {
30     android_compiler_barrier();
31 }
32 #else
android_memory_barrier(void)33 extern inline void android_memory_barrier(void)
34 {
35     __asm__ __volatile__ ("mfence" : : : "memory");
36 }
37 #endif
38 
android_atomic_acquire_load(volatile const int32_t * ptr)39 extern inline int32_t android_atomic_acquire_load(volatile const int32_t *ptr)
40 {
41     int32_t value = *ptr;
42     android_compiler_barrier();
43     return value;
44 }
45 
android_atomic_release_load(volatile const int32_t * ptr)46 extern inline int32_t android_atomic_release_load(volatile const int32_t *ptr)
47 {
48     android_memory_barrier();
49     return *ptr;
50 }
51 
android_atomic_acquire_store(int32_t value,volatile int32_t * ptr)52 extern inline void android_atomic_acquire_store(int32_t value,
53                                                 volatile int32_t *ptr)
54 {
55     *ptr = value;
56     android_memory_barrier();
57 }
58 
android_atomic_release_store(int32_t value,volatile int32_t * ptr)59 extern inline void android_atomic_release_store(int32_t value,
60                                                 volatile int32_t *ptr)
61 {
62     android_compiler_barrier();
63     *ptr = value;
64 }
65 
android_atomic_cas(int32_t old_value,int32_t new_value,volatile int32_t * ptr)66 extern inline int android_atomic_cas(int32_t old_value, int32_t new_value,
67                                      volatile int32_t *ptr)
68 {
69     int32_t prev;
70     __asm__ __volatile__ ("lock; cmpxchgl %1, %2"
71                           : "=a" (prev)
72                           : "q" (new_value), "m" (*ptr), "0" (old_value)
73                           : "memory");
74     return prev != old_value;
75 }
76 
android_atomic_acquire_cas(int32_t old_value,int32_t new_value,volatile int32_t * ptr)77 extern inline int android_atomic_acquire_cas(int32_t old_value,
78                                              int32_t new_value,
79                                              volatile int32_t *ptr)
80 {
81     /* Loads are not reordered with other loads. */
82     return android_atomic_cas(old_value, new_value, ptr);
83 }
84 
android_atomic_release_cas(int32_t old_value,int32_t new_value,volatile int32_t * ptr)85 extern inline int android_atomic_release_cas(int32_t old_value,
86                                              int32_t new_value,
87                                              volatile int32_t *ptr)
88 {
89     /* Stores are not reordered with other stores. */
90     return android_atomic_cas(old_value, new_value, ptr);
91 }
92 
android_atomic_swap(int32_t new_value,volatile int32_t * ptr)93 extern inline int32_t android_atomic_swap(int32_t new_value,
94                                           volatile int32_t *ptr)
95 {
96     __asm__ __volatile__ ("xchgl %1, %0"
97                           : "=r" (new_value)
98                           : "m" (*ptr), "0" (new_value)
99                           : "memory");
100     /* new_value now holds the old value of *ptr */
101     return new_value;
102 }
103 
android_atomic_add(int32_t increment,volatile int32_t * ptr)104 extern inline int32_t android_atomic_add(int32_t increment,
105                                          volatile int32_t *ptr)
106 {
107     __asm__ __volatile__ ("lock; xaddl %0, %1"
108                           : "+r" (increment), "+m" (*ptr)
109                           : : "memory");
110     /* increment now holds the old value of *ptr */
111     return increment;
112 }
113 
android_atomic_inc(volatile int32_t * addr)114 extern inline int32_t android_atomic_inc(volatile int32_t *addr)
115 {
116     return android_atomic_add(1, addr);
117 }
118 
android_atomic_dec(volatile int32_t * addr)119 extern inline int32_t android_atomic_dec(volatile int32_t *addr)
120 {
121     return android_atomic_add(-1, addr);
122 }
123 
android_atomic_and(int32_t value,volatile int32_t * ptr)124 extern inline int32_t android_atomic_and(int32_t value,
125                                          volatile int32_t *ptr)
126 {
127     int32_t prev, status;
128     do {
129         prev = *ptr;
130         status = android_atomic_cas(prev, prev & value, ptr);
131     } while (__builtin_expect(status != 0, 0));
132     return prev;
133 }
134 
android_atomic_or(int32_t value,volatile int32_t * ptr)135 extern inline int32_t android_atomic_or(int32_t value, volatile int32_t *ptr)
136 {
137     int32_t prev, status;
138     do {
139         prev = *ptr;
140         status = android_atomic_cas(prev, prev | value, ptr);
141     } while (__builtin_expect(status != 0, 0));
142     return prev;
143 }
144 
145 #endif /* ANDROID_CUTILS_ATOMIC_X86_H */
146