• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2011 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  #ifndef BIONIC_ATOMIC_ARM_H
17  #define BIONIC_ATOMIC_ARM_H
18  
__bionic_memory_barrier()19  __ATOMIC_INLINE__ void __bionic_memory_barrier() {
20  #if defined(ANDROID_SMP) && ANDROID_SMP == 1
21    __asm__ __volatile__ ( "dmb ish" : : : "memory" );
22  #else
23    /* A simple compiler barrier. */
24    __asm__ __volatile__ ( "" : : : "memory" );
25  #endif
26  }
27  
28  /* Compare-and-swap, without any explicit barriers. Note that this function
29   * returns 0 on success, and 1 on failure. The opposite convention is typically
30   * used on other platforms.
31   */
__bionic_cmpxchg(int32_t old_value,int32_t new_value,volatile int32_t * ptr)32  __ATOMIC_INLINE__ int __bionic_cmpxchg(int32_t old_value, int32_t new_value, volatile int32_t* ptr) {
33    int32_t prev, status;
34    do {
35      __asm__ __volatile__ (
36            "ldrex %0, [%3]\n"
37            "mov %1, #0\n"
38            "teq %0, %4\n"
39  #ifdef __thumb2__
40            "it eq\n"
41  #endif
42            "strexeq %1, %5, [%3]"
43            : "=&r" (prev), "=&r" (status), "+m"(*ptr)
44            : "r" (ptr), "Ir" (old_value), "r" (new_value)
45            : "cc");
46    } while (__builtin_expect(status != 0, 0));
47    return prev != old_value;
48  }
49  
50  /* Swap, without any explicit barriers. */
__bionic_swap(int32_t new_value,volatile int32_t * ptr)51  __ATOMIC_INLINE__ int32_t __bionic_swap(int32_t new_value, volatile int32_t* ptr) {
52    int32_t prev, status;
53    do {
54      __asm__ __volatile__ (
55            "ldrex %0, [%3]\n"
56            "strex %1, %4, [%3]"
57            : "=&r" (prev), "=&r" (status), "+m" (*ptr)
58            : "r" (ptr), "r" (new_value)
59            : "cc");
60    } while (__builtin_expect(status != 0, 0));
61    return prev;
62  }
63  
64  /* Atomic decrement, without explicit barriers. */
__bionic_atomic_dec(volatile int32_t * ptr)65  __ATOMIC_INLINE__ int32_t __bionic_atomic_dec(volatile int32_t* ptr) {
66    int32_t prev, tmp, status;
67    do {
68      __asm__ __volatile__ (
69            "ldrex %0, [%4]\n"
70            "sub %1, %0, #1\n"
71            "strex %2, %1, [%4]"
72            : "=&r" (prev), "=&r" (tmp), "=&r" (status), "+m"(*ptr)
73            : "r" (ptr)
74            : "cc");
75    } while (__builtin_expect(status != 0, 0));
76    return prev;
77  }
78  
79  #endif /* SYS_ATOMICS_ARM_H */
80